1
0
Fork 0
mirror of https://github.com/moby/moby.git synced 2022-11-09 12:21:53 -05:00
moby--moby/integration-cli/docker_cli_events_test.go
Josh Hawn 8936789919 Make FROM scratch a special cased 'no-base' spec
There has been a lot of discussion (issues 4242 and 5262) about making
`FROM scratch` either a special case or making `FROM` optional, implying
starting from an empty file system.

This patch makes the build command `FROM scratch` special cased from now on
and if used does not pull/set the the initial layer of the build to the ancient
image ID (511136ea..) but instead marks the build as having no base image. The
next command in the dockerfile will create an image with a parent image ID of "".
This means every image ever can now use one fewer layer!

This also makes the image name `scratch` a reserved name by the TagStore. You
will not be able to tag an image with this name from now on. If any users
currently have an image tagged as `scratch`, they will still be able to use that
image, but will not be able to tag a new image with that name.

Goodbye '511136ea3c5a64f264b78b5433614aec563103b4d4702f3ba7d4d2698e22c158',
it was nice knowing you.

Fixes #4242

Docker-DCO-1.1-Signed-off-by: Josh Hawn <josh.hawn@docker.com> (github: jlhawn)
2014-12-18 14:03:38 -08:00

345 lines
11 KiB
Go

package main
import (
"bufio"
"fmt"
"io/ioutil"
"os"
"os/exec"
"strconv"
"strings"
"testing"
"time"
"unicode"
"github.com/kr/pty"
)
func TestEventsUntag(t *testing.T) {
out, _, _ := dockerCmd(t, "images", "-q")
image := strings.Split(out, "\n")[0]
dockerCmd(t, "tag", image, "utest:tag1")
dockerCmd(t, "tag", image, "utest:tag2")
dockerCmd(t, "rmi", "utest:tag1")
dockerCmd(t, "rmi", "utest:tag2")
eventsCmd := exec.Command("timeout", "0.2", dockerBinary, "events", "--since=1")
out, _, _ = runCommandWithOutput(eventsCmd)
events := strings.Split(out, "\n")
nEvents := len(events)
// The last element after the split above will be an empty string, so we
// get the two elements before the last, which are the untags we're
// looking for.
for _, v := range events[nEvents-3 : nEvents-1] {
if !strings.Contains(v, "untag") {
t.Fatalf("event should be untag, not %#v", v)
}
}
logDone("events - untags are logged")
}
func TestEventsPause(t *testing.T) {
name := "testeventpause"
out, _, _ := dockerCmd(t, "images", "-q")
image := strings.Split(out, "\n")[0]
dockerCmd(t, "run", "-d", "--name", name, image, "sleep", "2")
dockerCmd(t, "pause", name)
dockerCmd(t, "unpause", name)
defer deleteAllContainers()
eventsCmd := exec.Command(dockerBinary, "events", "--since=0", fmt.Sprintf("--until=%d", time.Now().Unix()))
out, _, _ = runCommandWithOutput(eventsCmd)
events := strings.Split(out, "\n")
if len(events) <= 1 {
t.Fatalf("Missing expected event")
}
pauseEvent := strings.Fields(events[len(events)-3])
unpauseEvent := strings.Fields(events[len(events)-2])
if pauseEvent[len(pauseEvent)-1] != "pause" {
t.Fatalf("event should be pause, not %#v", pauseEvent)
}
if unpauseEvent[len(unpauseEvent)-1] != "unpause" {
t.Fatalf("event should be unpause, not %#v", unpauseEvent)
}
waitCmd := exec.Command(dockerBinary, "wait", name)
if waitOut, _, err := runCommandWithOutput(waitCmd); err != nil {
t.Fatalf("error thrown while waiting for container: %s, %v", waitOut, err)
}
logDone("events - pause/unpause is logged")
}
func TestEventsContainerFailStartDie(t *testing.T) {
defer deleteAllContainers()
out, _, _ := dockerCmd(t, "images", "-q")
image := strings.Split(out, "\n")[0]
eventsCmd := exec.Command(dockerBinary, "run", "-d", "--name", "testeventdie", image, "blerg")
_, _, err := runCommandWithOutput(eventsCmd)
if err == nil {
t.Fatalf("Container run with command blerg should have failed, but it did not")
}
eventsCmd = exec.Command(dockerBinary, "events", "--since=0", fmt.Sprintf("--until=%d", time.Now().Unix()))
out, _, _ = runCommandWithOutput(eventsCmd)
events := strings.Split(out, "\n")
if len(events) <= 1 {
t.Fatalf("Missing expected event")
}
startEvent := strings.Fields(events[len(events)-3])
dieEvent := strings.Fields(events[len(events)-2])
if startEvent[len(startEvent)-1] != "start" {
t.Fatalf("event should be start, not %#v", startEvent)
}
if dieEvent[len(dieEvent)-1] != "die" {
t.Fatalf("event should be die, not %#v", dieEvent)
}
logDone("events - container failed to start logs die")
}
func TestEventsLimit(t *testing.T) {
defer deleteAllContainers()
for i := 0; i < 30; i++ {
dockerCmd(t, "run", "busybox", "echo", strconv.Itoa(i))
}
eventsCmd := exec.Command(dockerBinary, "events", "--since=0", fmt.Sprintf("--until=%d", time.Now().Unix()))
out, _, _ := runCommandWithOutput(eventsCmd)
events := strings.Split(out, "\n")
nEvents := len(events) - 1
if nEvents != 64 {
t.Fatalf("events should be limited to 64, but received %d", nEvents)
}
logDone("events - limited to 64 entries")
}
func TestEventsContainerEvents(t *testing.T) {
dockerCmd(t, "run", "--rm", "busybox", "true")
eventsCmd := exec.Command(dockerBinary, "events", "--since=0", fmt.Sprintf("--until=%d", time.Now().Unix()))
out, exitCode, err := runCommandWithOutput(eventsCmd)
if exitCode != 0 || err != nil {
t.Fatalf("Failed to get events with exit code %d: %s", exitCode, err)
}
events := strings.Split(out, "\n")
events = events[:len(events)-1]
if len(events) < 4 {
t.Fatalf("Missing expected event")
}
createEvent := strings.Fields(events[len(events)-4])
startEvent := strings.Fields(events[len(events)-3])
dieEvent := strings.Fields(events[len(events)-2])
destroyEvent := strings.Fields(events[len(events)-1])
if createEvent[len(createEvent)-1] != "create" {
t.Fatalf("event should be create, not %#v", createEvent)
}
if startEvent[len(startEvent)-1] != "start" {
t.Fatalf("event should be start, not %#v", startEvent)
}
if dieEvent[len(dieEvent)-1] != "die" {
t.Fatalf("event should be die, not %#v", dieEvent)
}
if destroyEvent[len(destroyEvent)-1] != "destroy" {
t.Fatalf("event should be destroy, not %#v", destroyEvent)
}
logDone("events - container create, start, die, destroy is logged")
}
func TestEventsImageUntagDelete(t *testing.T) {
name := "testimageevents"
defer deleteImages(name)
_, err := buildImage(name,
`FROM scratch
MAINTAINER "docker"`,
true)
if err != nil {
t.Fatal(err)
}
if err := deleteImages(name); err != nil {
t.Fatal(err)
}
eventsCmd := exec.Command(dockerBinary, "events", "--since=0", fmt.Sprintf("--until=%d", time.Now().Unix()))
out, exitCode, err := runCommandWithOutput(eventsCmd)
if exitCode != 0 || err != nil {
t.Fatalf("Failed to get events with exit code %d: %s", exitCode, err)
}
events := strings.Split(out, "\n")
t.Log(events)
events = events[:len(events)-1]
if len(events) < 2 {
t.Fatalf("Missing expected event")
}
untagEvent := strings.Fields(events[len(events)-2])
deleteEvent := strings.Fields(events[len(events)-1])
if untagEvent[len(untagEvent)-1] != "untag" {
t.Fatalf("untag should be untag, not %#v", untagEvent)
}
if deleteEvent[len(deleteEvent)-1] != "delete" {
t.Fatalf("delete should be delete, not %#v", deleteEvent)
}
logDone("events - image untag, delete is logged")
}
// #5979
func TestEventsRedirectStdout(t *testing.T) {
since := time.Now().Unix()
dockerCmd(t, "run", "busybox", "true")
defer deleteAllContainers()
file, err := ioutil.TempFile("", "")
if err != nil {
t.Fatalf("could not create temp file: %v", err)
}
defer os.Remove(file.Name())
command := fmt.Sprintf("%s events --since=%d --until=%d > %s", dockerBinary, since, time.Now().Unix(), file.Name())
_, tty, err := pty.Open()
if err != nil {
t.Fatalf("Could not open pty: %v", err)
}
cmd := exec.Command("sh", "-c", command)
cmd.Stdin = tty
cmd.Stdout = tty
cmd.Stderr = tty
if err := cmd.Run(); err != nil {
t.Fatalf("run err for command %q: %v", command, err)
}
scanner := bufio.NewScanner(file)
for scanner.Scan() {
for _, c := range scanner.Text() {
if unicode.IsControl(c) {
t.Fatalf("found control character %v", []byte(string(c)))
}
}
}
if err := scanner.Err(); err != nil {
t.Fatalf("Scan err for command %q: %v", command, err)
}
logDone("events - redirect stdout")
}
func TestEventsImagePull(t *testing.T) {
since := time.Now().Unix()
pullCmd := exec.Command(dockerBinary, "pull", "hello-world")
if out, _, err := runCommandWithOutput(pullCmd); err != nil {
t.Fatalf("pulling the hello-world image from has failed: %s, %v", out, err)
}
eventsCmd := exec.Command(dockerBinary, "events",
fmt.Sprintf("--since=%d", since),
fmt.Sprintf("--until=%d", time.Now().Unix()))
out, _, _ := runCommandWithOutput(eventsCmd)
events := strings.Split(strings.TrimSpace(out), "\n")
event := strings.TrimSpace(events[len(events)-1])
if !strings.HasSuffix(event, "hello-world:latest: pull") {
t.Fatalf("Missing pull event - got:%q", event)
}
logDone("events - image pull is logged")
}
func TestEventsImageImport(t *testing.T) {
since := time.Now().Unix()
defer deleteImages("cirros")
server, err := fileServer(map[string]string{
"/cirros.tar.gz": "/cirros.tar.gz",
})
if err != nil {
t.Fatal(err)
}
defer server.Close()
fileURL := fmt.Sprintf("%s/cirros.tar.gz", server.URL)
importCmd := exec.Command(dockerBinary, "import", fileURL, "cirros")
out, _, err := runCommandWithOutput(importCmd)
if err != nil {
t.Errorf("import failed with errors: %v, output: %q", err, out)
}
eventsCmd := exec.Command(dockerBinary, "events",
fmt.Sprintf("--since=%d", since),
fmt.Sprintf("--until=%d", time.Now().Unix()))
out, _, _ = runCommandWithOutput(eventsCmd)
events := strings.Split(strings.TrimSpace(out), "\n")
event := strings.TrimSpace(events[len(events)-1])
if !strings.HasSuffix(event, ": import") {
t.Fatalf("Missing pull event - got:%q", event)
}
logDone("events - image import is logged")
}
func TestEventsFilters(t *testing.T) {
since := time.Now().Unix()
out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "run", "--rm", "busybox", "true"))
if err != nil {
t.Fatal(out, err)
}
out, _, err = runCommandWithOutput(exec.Command(dockerBinary, "run", "--rm", "busybox", "true"))
if err != nil {
t.Fatal(out, err)
}
eventsCmd := exec.Command(dockerBinary, "events", fmt.Sprintf("--since=%d", since), fmt.Sprintf("--until=%d", time.Now().Unix()), "--filter", "event=die")
out, exitCode, err := runCommandWithOutput(eventsCmd)
if exitCode != 0 || err != nil {
t.Fatalf("Failed to get events with exit code %d: %s", exitCode, err)
}
events := strings.Split(out, "\n")
events = events[:len(events)-1]
if len(events) != 2 {
t.Fatalf("Expected 2 events, got %d: %v", len(events), events)
}
dieEvent := strings.Fields(events[len(events)-1])
if dieEvent[len(dieEvent)-1] != "die" {
t.Fatalf("event should be die, not %#v", dieEvent)
}
dieEvent = strings.Fields(events[len(events)-2])
if dieEvent[len(dieEvent)-1] != "die" {
t.Fatalf("event should be die, not %#v", dieEvent)
}
eventsCmd = exec.Command(dockerBinary, "events", fmt.Sprintf("--since=%d", since), fmt.Sprintf("--until=%d", time.Now().Unix()), "--filter", "event=die", "--filter", "event=start")
out, exitCode, err = runCommandWithOutput(eventsCmd)
if exitCode != 0 || err != nil {
t.Fatalf("Failed to get events with exit code %d: %s", exitCode, err)
}
events = strings.Split(out, "\n")
events = events[:len(events)-1]
if len(events) != 4 {
t.Fatalf("Expected 4 events, got %d: %v", len(events), events)
}
startEvent := strings.Fields(events[len(events)-4])
if startEvent[len(startEvent)-1] != "start" {
t.Fatalf("event should be start, not %#v", startEvent)
}
dieEvent = strings.Fields(events[len(events)-3])
if dieEvent[len(dieEvent)-1] != "die" {
t.Fatalf("event should be die, not %#v", dieEvent)
}
startEvent = strings.Fields(events[len(events)-2])
if startEvent[len(startEvent)-1] != "start" {
t.Fatalf("event should be start, not %#v", startEvent)
}
dieEvent = strings.Fields(events[len(events)-1])
if dieEvent[len(dieEvent)-1] != "die" {
t.Fatalf("event should be die, not %#v", dieEvent)
}
logDone("events - filters")
}