Merge pull request #10806 from ahmetalpbalkan/win-cli/TestSave-fix

integration-cli: use pipes for save/load tests
This commit is contained in:
Jessie Frazelle 2015-02-18 22:42:06 -08:00
commit cd9769c55e
2 changed files with 110 additions and 87 deletions

View File

@ -14,14 +14,6 @@ import (
// save a repo using gz compression and try to load it using stdout // save a repo using gz compression and try to load it using stdout
func TestSaveXzAndLoadRepoStdout(t *testing.T) { func TestSaveXzAndLoadRepoStdout(t *testing.T) {
tempDir, err := ioutil.TempDir("", "test-save-xz-gz-load-repo-stdout")
if err != nil {
t.Fatal(err)
}
defer os.RemoveAll(tempDir)
tarballPath := filepath.Join(tempDir, "foobar-save-load-test.tar.xz.gz")
runCmd := exec.Command(dockerBinary, "run", "-d", "busybox", "true") runCmd := exec.Command(dockerBinary, "run", "-d", "busybox", "true")
out, _, err := runCommandWithOutput(runCmd) out, _, err := runCommandWithOutput(runCmd)
if err != nil { if err != nil {
@ -50,18 +42,17 @@ func TestSaveXzAndLoadRepoStdout(t *testing.T) {
t.Fatalf("the repo should exist before saving it: %v %v", before, err) t.Fatalf("the repo should exist before saving it: %v %v", before, err)
} }
saveCmdTemplate := `%v save %v | xz -c | gzip -c > %s` repoTarball, _, err := runCommandPipelineWithOutput(
saveCmdFinal := fmt.Sprintf(saveCmdTemplate, dockerBinary, repoName, tarballPath) exec.Command(dockerBinary, "save", repoName),
saveCmd := exec.Command("bash", "-c", saveCmdFinal) exec.Command("xz", "-c"),
out, _, err = runCommandWithOutput(saveCmd) exec.Command("gzip", "-c"))
if err != nil { if err != nil {
t.Fatalf("failed to save repo: %v %v", out, err) t.Fatalf("failed to save repo: %v %v", out, err)
} }
deleteImages(repoName) deleteImages(repoName)
loadCmdFinal := fmt.Sprintf(`cat %s | docker load`, tarballPath) loadCmd := exec.Command(dockerBinary, "load")
loadCmd := exec.Command("bash", "-c", loadCmdFinal) loadCmd.Stdin = strings.NewReader(repoTarball)
out, _, err = runCommandWithOutput(loadCmd) out, _, err = runCommandWithOutput(loadCmd)
if err == nil { if err == nil {
t.Fatalf("expected error, but succeeded with no error and output: %v", out) t.Fatalf("expected error, but succeeded with no error and output: %v", out)
@ -73,7 +64,6 @@ func TestSaveXzAndLoadRepoStdout(t *testing.T) {
t.Fatalf("the repo should not exist: %v", after) t.Fatalf("the repo should not exist: %v", after)
} }
deleteContainer(cleanedContainerID)
deleteImages(repoName) deleteImages(repoName)
logDone("load - save a repo with xz compression & load it using stdout") logDone("load - save a repo with xz compression & load it using stdout")
@ -81,14 +71,6 @@ func TestSaveXzAndLoadRepoStdout(t *testing.T) {
// save a repo using xz+gz compression and try to load it using stdout // save a repo using xz+gz compression and try to load it using stdout
func TestSaveXzGzAndLoadRepoStdout(t *testing.T) { func TestSaveXzGzAndLoadRepoStdout(t *testing.T) {
tempDir, err := ioutil.TempDir("", "test-save-xz-gz-load-repo-stdout")
if err != nil {
t.Fatal(err)
}
defer os.RemoveAll(tempDir)
tarballPath := filepath.Join(tempDir, "foobar-save-load-test.tar.xz.gz")
runCmd := exec.Command(dockerBinary, "run", "-d", "busybox", "true") runCmd := exec.Command(dockerBinary, "run", "-d", "busybox", "true")
out, _, err := runCommandWithOutput(runCmd) out, _, err := runCommandWithOutput(runCmd)
if err != nil { if err != nil {
@ -117,18 +99,18 @@ func TestSaveXzGzAndLoadRepoStdout(t *testing.T) {
t.Fatalf("the repo should exist before saving it: %v %v", before, err) t.Fatalf("the repo should exist before saving it: %v %v", before, err)
} }
saveCmdTemplate := `%v save %v | xz -c | gzip -c > %s` out, _, err = runCommandPipelineWithOutput(
saveCmdFinal := fmt.Sprintf(saveCmdTemplate, dockerBinary, repoName, tarballPath) exec.Command(dockerBinary, "save", repoName),
saveCmd := exec.Command("bash", "-c", saveCmdFinal) exec.Command("xz", "-c"),
out, _, err = runCommandWithOutput(saveCmd) exec.Command("gzip", "-c"))
if err != nil { if err != nil {
t.Fatalf("failed to save repo: %v %v", out, err) t.Fatalf("failed to save repo: %v %v", out, err)
} }
deleteImages(repoName) deleteImages(repoName)
loadCmdFinal := fmt.Sprintf(`cat %s | docker load`, tarballPath) loadCmd := exec.Command(dockerBinary, "load")
loadCmd := exec.Command("bash", "-c", loadCmdFinal) loadCmd.Stdin = strings.NewReader(out)
out, _, err = runCommandWithOutput(loadCmd) out, _, err = runCommandWithOutput(loadCmd)
if err == nil { if err == nil {
t.Fatalf("expected error, but succeeded with no error and output: %v", out) t.Fatalf("expected error, but succeeded with no error and output: %v", out)
@ -149,43 +131,40 @@ func TestSaveXzGzAndLoadRepoStdout(t *testing.T) {
func TestSaveSingleTag(t *testing.T) { func TestSaveSingleTag(t *testing.T) {
repoName := "foobar-save-single-tag-test" repoName := "foobar-save-single-tag-test"
tagCmdFinal := fmt.Sprintf("%v tag busybox:latest %v:latest", dockerBinary, repoName) tagCmd := exec.Command(dockerBinary, "tag", "busybox:latest", fmt.Sprintf("%v:latest", repoName))
tagCmd := exec.Command("bash", "-c", tagCmdFinal) defer deleteImages(repoName)
if out, _, err := runCommandWithOutput(tagCmd); err != nil { if out, _, err := runCommandWithOutput(tagCmd); err != nil {
t.Fatalf("failed to tag repo: %s, %v", out, err) t.Fatalf("failed to tag repo: %s, %v", out, err)
} }
idCmdFinal := fmt.Sprintf("%v images -q --no-trunc %v", dockerBinary, repoName) idCmd := exec.Command(dockerBinary, "images", "-q", "--no-trunc", repoName)
idCmd := exec.Command("bash", "-c", idCmdFinal)
out, _, err := runCommandWithOutput(idCmd) out, _, err := runCommandWithOutput(idCmd)
if err != nil { if err != nil {
t.Fatalf("failed to get repo ID: %s, %v", out, err) t.Fatalf("failed to get repo ID: %s, %v", out, err)
} }
cleanedImageID := stripTrailingCharacters(out) cleanedImageID := stripTrailingCharacters(out)
saveCmdFinal := fmt.Sprintf("%v save %v:latest | tar t | grep -E '(^repositories$|%v)'", dockerBinary, repoName, cleanedImageID) out, _, err = runCommandPipelineWithOutput(
saveCmd := exec.Command("bash", "-c", saveCmdFinal) exec.Command(dockerBinary, "save", fmt.Sprintf("%v:latest", repoName)),
if out, _, err = runCommandWithOutput(saveCmd); err != nil { exec.Command("tar", "t"),
exec.Command("grep", "-E", fmt.Sprintf("(^repositories$|%v)", cleanedImageID)))
if err != nil {
t.Fatalf("failed to save repo with image ID and 'repositories' file: %s, %v", out, err) t.Fatalf("failed to save repo with image ID and 'repositories' file: %s, %v", out, err)
} }
deleteImages(repoName)
logDone("save - save a specific image:tag") logDone("save - save a specific image:tag")
} }
func TestSaveImageId(t *testing.T) { func TestSaveImageId(t *testing.T) {
repoName := "foobar-save-image-id-test" repoName := "foobar-save-image-id-test"
tagCmdFinal := fmt.Sprintf("%v tag emptyfs:latest %v:latest", dockerBinary, repoName) tagCmd := exec.Command(dockerBinary, "tag", "emptyfs:latest", fmt.Sprintf("%v:latest", repoName))
tagCmd := exec.Command("bash", "-c", tagCmdFinal) defer deleteImages(repoName)
if out, _, err := runCommandWithOutput(tagCmd); err != nil { if out, _, err := runCommandWithOutput(tagCmd); err != nil {
t.Fatalf("failed to tag repo: %s, %v", out, err) t.Fatalf("failed to tag repo: %s, %v", out, err)
} }
idLongCmdFinal := fmt.Sprintf("%v images -q --no-trunc %v", dockerBinary, repoName) idLongCmd := exec.Command(dockerBinary, "images", "-q", "--no-trunc", repoName)
idLongCmd := exec.Command("bash", "-c", idLongCmdFinal)
out, _, err := runCommandWithOutput(idLongCmd) out, _, err := runCommandWithOutput(idLongCmd)
if err != nil { if err != nil {
t.Fatalf("failed to get repo ID: %s, %v", out, err) t.Fatalf("failed to get repo ID: %s, %v", out, err)
@ -193,8 +172,7 @@ func TestSaveImageId(t *testing.T) {
cleanedLongImageID := stripTrailingCharacters(out) cleanedLongImageID := stripTrailingCharacters(out)
idShortCmdFinal := fmt.Sprintf("%v images -q %v", dockerBinary, repoName) idShortCmd := exec.Command(dockerBinary, "images", "-q", repoName)
idShortCmd := exec.Command("bash", "-c", idShortCmdFinal)
out, _, err = runCommandWithOutput(idShortCmd) out, _, err = runCommandWithOutput(idShortCmd)
if err != nil { if err != nil {
t.Fatalf("failed to get repo short ID: %s, %v", out, err) t.Fatalf("failed to get repo short ID: %s, %v", out, err)
@ -202,13 +180,32 @@ func TestSaveImageId(t *testing.T) {
cleanedShortImageID := stripTrailingCharacters(out) cleanedShortImageID := stripTrailingCharacters(out)
saveCmdFinal := fmt.Sprintf("%v save %v | tar t | grep %v", dockerBinary, cleanedShortImageID, cleanedLongImageID) saveCmd := exec.Command(dockerBinary, "save", cleanedShortImageID)
saveCmd := exec.Command("bash", "-c", saveCmdFinal) tarCmd := exec.Command("tar", "t")
if out, _, err = runCommandWithOutput(saveCmd); err != nil { tarCmd.Stdin, err = saveCmd.StdoutPipe()
t.Fatalf("failed to save repo with image ID: %s, %v", out, err) if err != nil {
t.Fatalf("cannot set stdout pipe for tar: %v", err)
}
grepCmd := exec.Command("grep", cleanedLongImageID)
grepCmd.Stdin, err = tarCmd.StdoutPipe()
if err != nil {
t.Fatalf("cannot set stdout pipe for grep: %v", err)
} }
deleteImages(repoName) if err = tarCmd.Start(); err != nil {
t.Fatalf("tar failed with error: %v", err)
}
if err = saveCmd.Start(); err != nil {
t.Fatalf("docker save failed with error: %v", err)
}
defer saveCmd.Wait()
defer tarCmd.Wait()
out, _, err = runCommandWithOutput(grepCmd)
if err != nil {
t.Fatalf("failed to save repo with image ID: %s, %v", out, err)
}
logDone("save - save a image by ID") logDone("save - save a image by ID")
} }
@ -222,6 +219,7 @@ func TestSaveAndLoadRepoFlags(t *testing.T) {
} }
cleanedContainerID := stripTrailingCharacters(out) cleanedContainerID := stripTrailingCharacters(out)
defer deleteContainer(cleanedContainerID)
repoName := "foobar-save-load-test" repoName := "foobar-save-load-test"
@ -231,6 +229,7 @@ func TestSaveAndLoadRepoFlags(t *testing.T) {
} }
commitCmd := exec.Command(dockerBinary, "commit", cleanedContainerID, repoName) commitCmd := exec.Command(dockerBinary, "commit", cleanedContainerID, repoName)
deleteImages(repoName)
if out, _, err = runCommandWithOutput(commitCmd); err != nil { if out, _, err = runCommandWithOutput(commitCmd); err != nil {
t.Fatalf("failed to commit container: %s, %v", out, err) t.Fatalf("failed to commit container: %s, %v", out, err)
} }
@ -239,21 +238,14 @@ func TestSaveAndLoadRepoFlags(t *testing.T) {
before, _, err := runCommandWithOutput(inspectCmd) before, _, err := runCommandWithOutput(inspectCmd)
if err != nil { if err != nil {
t.Fatalf("the repo should exist before saving it: %s, %v", before, err) t.Fatalf("the repo should exist before saving it: %s, %v", before, err)
} }
saveCmdTemplate := `%v save -o /tmp/foobar-save-load-test.tar %v` out, _, err = runCommandPipelineWithOutput(
saveCmdFinal := fmt.Sprintf(saveCmdTemplate, dockerBinary, repoName) exec.Command(dockerBinary, "save", repoName),
saveCmd := exec.Command("bash", "-c", saveCmdFinal) exec.Command(dockerBinary, "load"))
if out, _, err = runCommandWithOutput(saveCmd); err != nil { if err != nil {
t.Fatalf("failed to save repo: %s, %v", out, err) t.Fatalf("failed to save and load repo: %s, %v", out, err)
}
deleteImages(repoName)
loadCmdFinal := `docker load -i /tmp/foobar-save-load-test.tar`
loadCmd := exec.Command("bash", "-c", loadCmdFinal)
if out, _, err = runCommandWithOutput(loadCmd); err != nil {
t.Fatalf("failed to load repo: %s, %v", out, err)
} }
inspectCmd = exec.Command(dockerBinary, "inspect", repoName) inspectCmd = exec.Command(dockerBinary, "inspect", repoName)
@ -266,11 +258,6 @@ func TestSaveAndLoadRepoFlags(t *testing.T) {
t.Fatalf("inspect is not the same after a save / load") t.Fatalf("inspect is not the same after a save / load")
} }
deleteContainer(cleanedContainerID)
deleteImages(repoName)
os.Remove("/tmp/foobar-save-load-test.tar")
logDone("save - save a repo using -o && load a repo using -i") logDone("save - save a repo using -o && load a repo using -i")
} }
@ -278,29 +265,29 @@ func TestSaveMultipleNames(t *testing.T) {
repoName := "foobar-save-multi-name-test" repoName := "foobar-save-multi-name-test"
// Make one image // Make one image
tagCmdFinal := fmt.Sprintf("%v tag emptyfs:latest %v-one:latest", dockerBinary, repoName) tagCmd := exec.Command(dockerBinary, "tag", "emptyfs:latest", fmt.Sprintf("%v-one:latest", repoName))
tagCmd := exec.Command("bash", "-c", tagCmdFinal)
if out, _, err := runCommandWithOutput(tagCmd); err != nil { if out, _, err := runCommandWithOutput(tagCmd); err != nil {
t.Fatalf("failed to tag repo: %s, %v", out, err) t.Fatalf("failed to tag repo: %s, %v", out, err)
} }
defer deleteImages(repoName + "-one") defer deleteImages(repoName + "-one")
// Make two images // Make two images
tagCmdFinal = fmt.Sprintf("%v tag emptyfs:latest %v-two:latest", dockerBinary, repoName) tagCmd = exec.Command(dockerBinary, "tag", "emptyfs:latest", fmt.Sprintf("%v-two:latest", repoName))
tagCmd = exec.Command("bash", "-c", tagCmdFinal) out, _, err := runCommandWithOutput(tagCmd)
if out, _, err := runCommandWithOutput(tagCmd); err != nil { if err != nil {
t.Fatalf("failed to tag repo: %s, %v", out, err) t.Fatalf("failed to tag repo: %s, %v", out, err)
} }
defer deleteImages(repoName + "-two") defer deleteImages(repoName + "-two")
saveCmdFinal := fmt.Sprintf("%v save %v-one %v-two:latest | tar xO repositories | grep -q -E '(-one|-two)'", dockerBinary, repoName, repoName) out, _, err = runCommandPipelineWithOutput(
saveCmd := exec.Command("bash", "-c", saveCmdFinal) exec.Command(dockerBinary, "save", fmt.Sprintf("%v-one", repoName), fmt.Sprintf("%v-two:latest", repoName)),
if out, _, err := runCommandWithOutput(saveCmd); err != nil { exec.Command("tar", "xO", "repositories"),
exec.Command("grep", "-q", "-E", "(-one|-two)"),
)
if err != nil {
t.Fatalf("failed to save multiple repos: %s, %v", out, err) t.Fatalf("failed to save multiple repos: %s, %v", out, err)
} }
deleteImages(repoName)
logDone("save - save by multiple names") logDone("save - save by multiple names")
} }
@ -316,14 +303,13 @@ func TestSaveRepoWithMultipleImages(t *testing.T) {
t.Fatalf("failed to create a container: %v %v", out, err) t.Fatalf("failed to create a container: %v %v", out, err)
} }
cleanedContainerID := stripTrailingCharacters(out) cleanedContainerID := stripTrailingCharacters(out)
defer deleteContainer(cleanedContainerID)
commitCmd := exec.Command(dockerBinary, "commit", cleanedContainerID, tag) commitCmd := exec.Command(dockerBinary, "commit", cleanedContainerID, tag)
if out, _, err = runCommandWithOutput(commitCmd); err != nil { if out, _, err = runCommandWithOutput(commitCmd); err != nil {
t.Fatalf("failed to commit container: %v %v", out, err) t.Fatalf("failed to commit container: %v %v", out, err)
} }
imageID := stripTrailingCharacters(out) imageID := stripTrailingCharacters(out)
deleteContainer(cleanedContainerID)
return imageID return imageID
} }
@ -332,23 +318,25 @@ func TestSaveRepoWithMultipleImages(t *testing.T) {
tagBar := repoName + ":bar" tagBar := repoName + ":bar"
idFoo := makeImage("busybox:latest", tagFoo) idFoo := makeImage("busybox:latest", tagFoo)
defer deleteImages(idFoo)
idBar := makeImage("busybox:latest", tagBar) idBar := makeImage("busybox:latest", tagBar)
defer deleteImages(idBar)
deleteImages(repoName) deleteImages(repoName)
// create the archive // create the archive
saveCmdFinal := fmt.Sprintf("%v save %v | tar t | grep 'VERSION' |cut -d / -f1", dockerBinary, repoName) out, _, err := runCommandPipelineWithOutput(
saveCmd := exec.Command("bash", "-c", saveCmdFinal) exec.Command(dockerBinary, "save", repoName),
out, _, err := runCommandWithOutput(saveCmd) exec.Command("tar", "t"),
exec.Command("grep", "VERSION"),
exec.Command("cut", "-d", "/", "-f1"))
if err != nil { if err != nil {
t.Fatalf("failed to save multiple images: %s, %v", out, err) t.Fatalf("failed to save multiple images: %s, %v", out, err)
} }
actual := strings.Split(stripTrailingCharacters(out), "\n") actual := strings.Split(stripTrailingCharacters(out), "\n")
// make the list of expected layers // make the list of expected layers
historyCmdFinal := fmt.Sprintf("%v history -q --no-trunc %v", dockerBinary, "busybox:latest") out, _, err = runCommandWithOutput(exec.Command(dockerBinary, "history", "-q", "--no-trunc", "busybox:latest"))
historyCmd := exec.Command("bash", "-c", historyCmdFinal)
out, _, err = runCommandWithOutput(historyCmd)
if err != nil { if err != nil {
t.Fatalf("failed to get history: %s, %v", out, err) t.Fatalf("failed to get history: %s, %v", out, err)
} }

View File

@ -3,6 +3,7 @@ package main
import ( import (
"bytes" "bytes"
"encoding/json" "encoding/json"
"errors"
"fmt" "fmt"
"io" "io"
"math/rand" "math/rand"
@ -95,6 +96,40 @@ func runCommand(cmd *exec.Cmd) (exitCode int, err error) {
return return
} }
func runCommandPipelineWithOutput(cmds ...*exec.Cmd) (output string, exitCode int, err error) {
if len(cmds) < 2 {
return "", 0, errors.New("pipeline does not have multiple cmds")
}
// connect stdin of each cmd to stdout pipe of previous cmd
for i, cmd := range cmds {
if i > 0 {
prevCmd := cmds[i-1]
cmd.Stdin, err = prevCmd.StdoutPipe()
if err != nil {
return "", 0, fmt.Errorf("cannot set stdout pipe for %s: %v", cmd.Path, err)
}
}
}
// start all cmds except the last
for _, cmd := range cmds[:len(cmds)-1] {
if err = cmd.Start(); err != nil {
return "", 0, fmt.Errorf("starting %s failed with error: %v", cmd.Path, err)
}
}
defer func() {
// wait all cmds except the last to release their resources
for _, cmd := range cmds[:len(cmds)-1] {
cmd.Wait()
}
}()
// wait on last cmd
return runCommandWithOutput(cmds[len(cmds)-1])
}
func logDone(message string) { func logDone(message string) {
fmt.Printf("[PASSED]: %s\n", message) fmt.Printf("[PASSED]: %s\n", message)
} }