integration-cli: use pipes for save/load tests
| ... | ... |
@@ -14,14 +14,6 @@ import ( |
| 14 | 14 |
|
| 15 | 15 |
// save a repo using gz compression and try to load it using stdout |
| 16 | 16 |
func TestSaveXzAndLoadRepoStdout(t *testing.T) {
|
| 17 |
- tempDir, err := ioutil.TempDir("", "test-save-xz-gz-load-repo-stdout")
|
|
| 18 |
- if err != nil {
|
|
| 19 |
- t.Fatal(err) |
|
| 20 |
- } |
|
| 21 |
- defer os.RemoveAll(tempDir) |
|
| 22 |
- |
|
| 23 |
- tarballPath := filepath.Join(tempDir, "foobar-save-load-test.tar.xz.gz") |
|
| 24 |
- |
|
| 25 | 17 |
runCmd := exec.Command(dockerBinary, "run", "-d", "busybox", "true") |
| 26 | 18 |
out, _, err := runCommandWithOutput(runCmd) |
| 27 | 19 |
if err != nil {
|
| ... | ... |
@@ -50,18 +42,17 @@ func TestSaveXzAndLoadRepoStdout(t *testing.T) {
|
| 50 | 50 |
t.Fatalf("the repo should exist before saving it: %v %v", before, err)
|
| 51 | 51 |
} |
| 52 | 52 |
|
| 53 |
- saveCmdTemplate := `%v save %v | xz -c | gzip -c > %s` |
|
| 54 |
- saveCmdFinal := fmt.Sprintf(saveCmdTemplate, dockerBinary, repoName, tarballPath) |
|
| 55 |
- saveCmd := exec.Command("bash", "-c", saveCmdFinal)
|
|
| 56 |
- out, _, err = runCommandWithOutput(saveCmd) |
|
| 53 |
+ repoTarball, _, err := runCommandPipelineWithOutput( |
|
| 54 |
+ exec.Command(dockerBinary, "save", repoName), |
|
| 55 |
+ exec.Command("xz", "-c"),
|
|
| 56 |
+ exec.Command("gzip", "-c"))
|
|
| 57 | 57 |
if err != nil {
|
| 58 | 58 |
t.Fatalf("failed to save repo: %v %v", out, err)
|
| 59 | 59 |
} |
| 60 |
- |
|
| 61 | 60 |
deleteImages(repoName) |
| 62 | 61 |
|
| 63 |
- loadCmdFinal := fmt.Sprintf(`cat %s | docker load`, tarballPath) |
|
| 64 |
- loadCmd := exec.Command("bash", "-c", loadCmdFinal)
|
|
| 62 |
+ loadCmd := exec.Command(dockerBinary, "load") |
|
| 63 |
+ loadCmd.Stdin = strings.NewReader(repoTarball) |
|
| 65 | 64 |
out, _, err = runCommandWithOutput(loadCmd) |
| 66 | 65 |
if err == nil {
|
| 67 | 66 |
t.Fatalf("expected error, but succeeded with no error and output: %v", out)
|
| ... | ... |
@@ -73,7 +64,6 @@ func TestSaveXzAndLoadRepoStdout(t *testing.T) {
|
| 73 | 73 |
t.Fatalf("the repo should not exist: %v", after)
|
| 74 | 74 |
} |
| 75 | 75 |
|
| 76 |
- deleteContainer(cleanedContainerID) |
|
| 77 | 76 |
deleteImages(repoName) |
| 78 | 77 |
|
| 79 | 78 |
logDone("load - save a repo with xz compression & load it using stdout")
|
| ... | ... |
@@ -81,14 +71,6 @@ func TestSaveXzAndLoadRepoStdout(t *testing.T) {
|
| 81 | 81 |
|
| 82 | 82 |
// save a repo using xz+gz compression and try to load it using stdout |
| 83 | 83 |
func TestSaveXzGzAndLoadRepoStdout(t *testing.T) {
|
| 84 |
- tempDir, err := ioutil.TempDir("", "test-save-xz-gz-load-repo-stdout")
|
|
| 85 |
- if err != nil {
|
|
| 86 |
- t.Fatal(err) |
|
| 87 |
- } |
|
| 88 |
- defer os.RemoveAll(tempDir) |
|
| 89 |
- |
|
| 90 |
- tarballPath := filepath.Join(tempDir, "foobar-save-load-test.tar.xz.gz") |
|
| 91 |
- |
|
| 92 | 84 |
runCmd := exec.Command(dockerBinary, "run", "-d", "busybox", "true") |
| 93 | 85 |
out, _, err := runCommandWithOutput(runCmd) |
| 94 | 86 |
if err != nil {
|
| ... | ... |
@@ -117,18 +99,18 @@ func TestSaveXzGzAndLoadRepoStdout(t *testing.T) {
|
| 117 | 117 |
t.Fatalf("the repo should exist before saving it: %v %v", before, err)
|
| 118 | 118 |
} |
| 119 | 119 |
|
| 120 |
- saveCmdTemplate := `%v save %v | xz -c | gzip -c > %s` |
|
| 121 |
- saveCmdFinal := fmt.Sprintf(saveCmdTemplate, dockerBinary, repoName, tarballPath) |
|
| 122 |
- saveCmd := exec.Command("bash", "-c", saveCmdFinal)
|
|
| 123 |
- out, _, err = runCommandWithOutput(saveCmd) |
|
| 120 |
+ out, _, err = runCommandPipelineWithOutput( |
|
| 121 |
+ exec.Command(dockerBinary, "save", repoName), |
|
| 122 |
+ exec.Command("xz", "-c"),
|
|
| 123 |
+ exec.Command("gzip", "-c"))
|
|
| 124 | 124 |
if err != nil {
|
| 125 | 125 |
t.Fatalf("failed to save repo: %v %v", out, err)
|
| 126 | 126 |
} |
| 127 | 127 |
|
| 128 | 128 |
deleteImages(repoName) |
| 129 | 129 |
|
| 130 |
- loadCmdFinal := fmt.Sprintf(`cat %s | docker load`, tarballPath) |
|
| 131 |
- loadCmd := exec.Command("bash", "-c", loadCmdFinal)
|
|
| 130 |
+ loadCmd := exec.Command(dockerBinary, "load") |
|
| 131 |
+ loadCmd.Stdin = strings.NewReader(out) |
|
| 132 | 132 |
out, _, err = runCommandWithOutput(loadCmd) |
| 133 | 133 |
if err == nil {
|
| 134 | 134 |
t.Fatalf("expected error, but succeeded with no error and output: %v", out)
|
| ... | ... |
@@ -149,43 +131,40 @@ func TestSaveXzGzAndLoadRepoStdout(t *testing.T) {
|
| 149 | 149 |
func TestSaveSingleTag(t *testing.T) {
|
| 150 | 150 |
repoName := "foobar-save-single-tag-test" |
| 151 | 151 |
|
| 152 |
- tagCmdFinal := fmt.Sprintf("%v tag busybox:latest %v:latest", dockerBinary, repoName)
|
|
| 153 |
- tagCmd := exec.Command("bash", "-c", tagCmdFinal)
|
|
| 152 |
+ tagCmd := exec.Command(dockerBinary, "tag", "busybox:latest", fmt.Sprintf("%v:latest", repoName))
|
|
| 153 |
+ defer deleteImages(repoName) |
|
| 154 | 154 |
if out, _, err := runCommandWithOutput(tagCmd); err != nil {
|
| 155 | 155 |
t.Fatalf("failed to tag repo: %s, %v", out, err)
|
| 156 | 156 |
} |
| 157 | 157 |
|
| 158 |
- idCmdFinal := fmt.Sprintf("%v images -q --no-trunc %v", dockerBinary, repoName)
|
|
| 159 |
- idCmd := exec.Command("bash", "-c", idCmdFinal)
|
|
| 158 |
+ idCmd := exec.Command(dockerBinary, "images", "-q", "--no-trunc", repoName) |
|
| 160 | 159 |
out, _, err := runCommandWithOutput(idCmd) |
| 161 | 160 |
if err != nil {
|
| 162 | 161 |
t.Fatalf("failed to get repo ID: %s, %v", out, err)
|
| 163 | 162 |
} |
| 164 |
- |
|
| 165 | 163 |
cleanedImageID := stripTrailingCharacters(out) |
| 166 | 164 |
|
| 167 |
- saveCmdFinal := fmt.Sprintf("%v save %v:latest | tar t | grep -E '(^repositories$|%v)'", dockerBinary, repoName, cleanedImageID)
|
|
| 168 |
- saveCmd := exec.Command("bash", "-c", saveCmdFinal)
|
|
| 169 |
- if out, _, err = runCommandWithOutput(saveCmd); err != nil {
|
|
| 165 |
+ out, _, err = runCommandPipelineWithOutput( |
|
| 166 |
+ exec.Command(dockerBinary, "save", fmt.Sprintf("%v:latest", repoName)),
|
|
| 167 |
+ exec.Command("tar", "t"),
|
|
| 168 |
+ exec.Command("grep", "-E", fmt.Sprintf("(^repositories$|%v)", cleanedImageID)))
|
|
| 169 |
+ if err != nil {
|
|
| 170 | 170 |
t.Fatalf("failed to save repo with image ID and 'repositories' file: %s, %v", out, err)
|
| 171 | 171 |
} |
| 172 | 172 |
|
| 173 |
- deleteImages(repoName) |
|
| 174 |
- |
|
| 175 | 173 |
logDone("save - save a specific image:tag")
|
| 176 | 174 |
} |
| 177 | 175 |
|
| 178 | 176 |
func TestSaveImageId(t *testing.T) {
|
| 179 | 177 |
repoName := "foobar-save-image-id-test" |
| 180 | 178 |
|
| 181 |
- tagCmdFinal := fmt.Sprintf("%v tag emptyfs:latest %v:latest", dockerBinary, repoName)
|
|
| 182 |
- tagCmd := exec.Command("bash", "-c", tagCmdFinal)
|
|
| 179 |
+ tagCmd := exec.Command(dockerBinary, "tag", "emptyfs:latest", fmt.Sprintf("%v:latest", repoName))
|
|
| 180 |
+ defer deleteImages(repoName) |
|
| 183 | 181 |
if out, _, err := runCommandWithOutput(tagCmd); err != nil {
|
| 184 | 182 |
t.Fatalf("failed to tag repo: %s, %v", out, err)
|
| 185 | 183 |
} |
| 186 | 184 |
|
| 187 |
- idLongCmdFinal := fmt.Sprintf("%v images -q --no-trunc %v", dockerBinary, repoName)
|
|
| 188 |
- idLongCmd := exec.Command("bash", "-c", idLongCmdFinal)
|
|
| 185 |
+ idLongCmd := exec.Command(dockerBinary, "images", "-q", "--no-trunc", repoName) |
|
| 189 | 186 |
out, _, err := runCommandWithOutput(idLongCmd) |
| 190 | 187 |
if err != nil {
|
| 191 | 188 |
t.Fatalf("failed to get repo ID: %s, %v", out, err)
|
| ... | ... |
@@ -193,8 +172,7 @@ func TestSaveImageId(t *testing.T) {
|
| 193 | 193 |
|
| 194 | 194 |
cleanedLongImageID := stripTrailingCharacters(out) |
| 195 | 195 |
|
| 196 |
- idShortCmdFinal := fmt.Sprintf("%v images -q %v", dockerBinary, repoName)
|
|
| 197 |
- idShortCmd := exec.Command("bash", "-c", idShortCmdFinal)
|
|
| 196 |
+ idShortCmd := exec.Command(dockerBinary, "images", "-q", repoName) |
|
| 198 | 197 |
out, _, err = runCommandWithOutput(idShortCmd) |
| 199 | 198 |
if err != nil {
|
| 200 | 199 |
t.Fatalf("failed to get repo short ID: %s, %v", out, err)
|
| ... | ... |
@@ -202,13 +180,32 @@ func TestSaveImageId(t *testing.T) {
|
| 202 | 202 |
|
| 203 | 203 |
cleanedShortImageID := stripTrailingCharacters(out) |
| 204 | 204 |
|
| 205 |
- saveCmdFinal := fmt.Sprintf("%v save %v | tar t | grep %v", dockerBinary, cleanedShortImageID, cleanedLongImageID)
|
|
| 206 |
- saveCmd := exec.Command("bash", "-c", saveCmdFinal)
|
|
| 207 |
- if out, _, err = runCommandWithOutput(saveCmd); err != nil {
|
|
| 208 |
- t.Fatalf("failed to save repo with image ID: %s, %v", out, err)
|
|
| 205 |
+ saveCmd := exec.Command(dockerBinary, "save", cleanedShortImageID) |
|
| 206 |
+ tarCmd := exec.Command("tar", "t")
|
|
| 207 |
+ tarCmd.Stdin, err = saveCmd.StdoutPipe() |
|
| 208 |
+ if err != nil {
|
|
| 209 |
+ t.Fatalf("cannot set stdout pipe for tar: %v", err)
|
|
| 210 |
+ } |
|
| 211 |
+ grepCmd := exec.Command("grep", cleanedLongImageID)
|
|
| 212 |
+ grepCmd.Stdin, err = tarCmd.StdoutPipe() |
|
| 213 |
+ if err != nil {
|
|
| 214 |
+ t.Fatalf("cannot set stdout pipe for grep: %v", err)
|
|
| 209 | 215 |
} |
| 210 | 216 |
|
| 211 |
- deleteImages(repoName) |
|
| 217 |
+ if err = tarCmd.Start(); err != nil {
|
|
| 218 |
+ t.Fatalf("tar failed with error: %v", err)
|
|
| 219 |
+ } |
|
| 220 |
+ if err = saveCmd.Start(); err != nil {
|
|
| 221 |
+ t.Fatalf("docker save failed with error: %v", err)
|
|
| 222 |
+ } |
|
| 223 |
+ defer saveCmd.Wait() |
|
| 224 |
+ defer tarCmd.Wait() |
|
| 225 |
+ |
|
| 226 |
+ out, _, err = runCommandWithOutput(grepCmd) |
|
| 227 |
+ |
|
| 228 |
+ if err != nil {
|
|
| 229 |
+ t.Fatalf("failed to save repo with image ID: %s, %v", out, err)
|
|
| 230 |
+ } |
|
| 212 | 231 |
|
| 213 | 232 |
logDone("save - save a image by ID")
|
| 214 | 233 |
} |
| ... | ... |
@@ -222,6 +219,7 @@ func TestSaveAndLoadRepoFlags(t *testing.T) {
|
| 222 | 222 |
} |
| 223 | 223 |
|
| 224 | 224 |
cleanedContainerID := stripTrailingCharacters(out) |
| 225 |
+ defer deleteContainer(cleanedContainerID) |
|
| 225 | 226 |
|
| 226 | 227 |
repoName := "foobar-save-load-test" |
| 227 | 228 |
|
| ... | ... |
@@ -231,6 +229,7 @@ func TestSaveAndLoadRepoFlags(t *testing.T) {
|
| 231 | 231 |
} |
| 232 | 232 |
|
| 233 | 233 |
commitCmd := exec.Command(dockerBinary, "commit", cleanedContainerID, repoName) |
| 234 |
+ deleteImages(repoName) |
|
| 234 | 235 |
if out, _, err = runCommandWithOutput(commitCmd); err != nil {
|
| 235 | 236 |
t.Fatalf("failed to commit container: %s, %v", out, err)
|
| 236 | 237 |
} |
| ... | ... |
@@ -239,21 +238,14 @@ func TestSaveAndLoadRepoFlags(t *testing.T) {
|
| 239 | 239 |
before, _, err := runCommandWithOutput(inspectCmd) |
| 240 | 240 |
if err != nil {
|
| 241 | 241 |
t.Fatalf("the repo should exist before saving it: %s, %v", before, err)
|
| 242 |
- } |
|
| 243 | 242 |
|
| 244 |
- saveCmdTemplate := `%v save -o /tmp/foobar-save-load-test.tar %v` |
|
| 245 |
- saveCmdFinal := fmt.Sprintf(saveCmdTemplate, dockerBinary, repoName) |
|
| 246 |
- saveCmd := exec.Command("bash", "-c", saveCmdFinal)
|
|
| 247 |
- if out, _, err = runCommandWithOutput(saveCmd); err != nil {
|
|
| 248 |
- t.Fatalf("failed to save repo: %s, %v", out, err)
|
|
| 249 | 243 |
} |
| 250 | 244 |
|
| 251 |
- deleteImages(repoName) |
|
| 252 |
- |
|
| 253 |
- loadCmdFinal := `docker load -i /tmp/foobar-save-load-test.tar` |
|
| 254 |
- loadCmd := exec.Command("bash", "-c", loadCmdFinal)
|
|
| 255 |
- if out, _, err = runCommandWithOutput(loadCmd); err != nil {
|
|
| 256 |
- t.Fatalf("failed to load repo: %s, %v", out, err)
|
|
| 245 |
+ out, _, err = runCommandPipelineWithOutput( |
|
| 246 |
+ exec.Command(dockerBinary, "save", repoName), |
|
| 247 |
+ exec.Command(dockerBinary, "load")) |
|
| 248 |
+ if err != nil {
|
|
| 249 |
+ t.Fatalf("failed to save and load repo: %s, %v", out, err)
|
|
| 257 | 250 |
} |
| 258 | 251 |
|
| 259 | 252 |
inspectCmd = exec.Command(dockerBinary, "inspect", repoName) |
| ... | ... |
@@ -266,11 +258,6 @@ func TestSaveAndLoadRepoFlags(t *testing.T) {
|
| 266 | 266 |
t.Fatalf("inspect is not the same after a save / load")
|
| 267 | 267 |
} |
| 268 | 268 |
|
| 269 |
- deleteContainer(cleanedContainerID) |
|
| 270 |
- deleteImages(repoName) |
|
| 271 |
- |
|
| 272 |
- os.Remove("/tmp/foobar-save-load-test.tar")
|
|
| 273 |
- |
|
| 274 | 269 |
logDone("save - save a repo using -o && load a repo using -i")
|
| 275 | 270 |
} |
| 276 | 271 |
|
| ... | ... |
@@ -278,29 +265,29 @@ func TestSaveMultipleNames(t *testing.T) {
|
| 278 | 278 |
repoName := "foobar-save-multi-name-test" |
| 279 | 279 |
|
| 280 | 280 |
// Make one image |
| 281 |
- tagCmdFinal := fmt.Sprintf("%v tag emptyfs:latest %v-one:latest", dockerBinary, repoName)
|
|
| 282 |
- tagCmd := exec.Command("bash", "-c", tagCmdFinal)
|
|
| 281 |
+ tagCmd := exec.Command(dockerBinary, "tag", "emptyfs:latest", fmt.Sprintf("%v-one:latest", repoName))
|
|
| 283 | 282 |
if out, _, err := runCommandWithOutput(tagCmd); err != nil {
|
| 284 | 283 |
t.Fatalf("failed to tag repo: %s, %v", out, err)
|
| 285 | 284 |
} |
| 286 | 285 |
defer deleteImages(repoName + "-one") |
| 287 | 286 |
|
| 288 | 287 |
// Make two images |
| 289 |
- tagCmdFinal = fmt.Sprintf("%v tag emptyfs:latest %v-two:latest", dockerBinary, repoName)
|
|
| 290 |
- tagCmd = exec.Command("bash", "-c", tagCmdFinal)
|
|
| 291 |
- if out, _, err := runCommandWithOutput(tagCmd); err != nil {
|
|
| 288 |
+ tagCmd = exec.Command(dockerBinary, "tag", "emptyfs:latest", fmt.Sprintf("%v-two:latest", repoName))
|
|
| 289 |
+ out, _, err := runCommandWithOutput(tagCmd) |
|
| 290 |
+ if err != nil {
|
|
| 292 | 291 |
t.Fatalf("failed to tag repo: %s, %v", out, err)
|
| 293 | 292 |
} |
| 294 | 293 |
defer deleteImages(repoName + "-two") |
| 295 | 294 |
|
| 296 |
- saveCmdFinal := fmt.Sprintf("%v save %v-one %v-two:latest | tar xO repositories | grep -q -E '(-one|-two)'", dockerBinary, repoName, repoName)
|
|
| 297 |
- saveCmd := exec.Command("bash", "-c", saveCmdFinal)
|
|
| 298 |
- if out, _, err := runCommandWithOutput(saveCmd); err != nil {
|
|
| 295 |
+ out, _, err = runCommandPipelineWithOutput( |
|
| 296 |
+ exec.Command(dockerBinary, "save", fmt.Sprintf("%v-one", repoName), fmt.Sprintf("%v-two:latest", repoName)),
|
|
| 297 |
+ exec.Command("tar", "xO", "repositories"),
|
|
| 298 |
+ exec.Command("grep", "-q", "-E", "(-one|-two)"),
|
|
| 299 |
+ ) |
|
| 300 |
+ if err != nil {
|
|
| 299 | 301 |
t.Fatalf("failed to save multiple repos: %s, %v", out, err)
|
| 300 | 302 |
} |
| 301 | 303 |
|
| 302 |
- deleteImages(repoName) |
|
| 303 |
- |
|
| 304 | 304 |
logDone("save - save by multiple names")
|
| 305 | 305 |
} |
| 306 | 306 |
|
| ... | ... |
@@ -316,14 +303,13 @@ func TestSaveRepoWithMultipleImages(t *testing.T) {
|
| 316 | 316 |
t.Fatalf("failed to create a container: %v %v", out, err)
|
| 317 | 317 |
} |
| 318 | 318 |
cleanedContainerID := stripTrailingCharacters(out) |
| 319 |
+ defer deleteContainer(cleanedContainerID) |
|
| 319 | 320 |
|
| 320 | 321 |
commitCmd := exec.Command(dockerBinary, "commit", cleanedContainerID, tag) |
| 321 | 322 |
if out, _, err = runCommandWithOutput(commitCmd); err != nil {
|
| 322 | 323 |
t.Fatalf("failed to commit container: %v %v", out, err)
|
| 323 | 324 |
} |
| 324 | 325 |
imageID := stripTrailingCharacters(out) |
| 325 |
- |
|
| 326 |
- deleteContainer(cleanedContainerID) |
|
| 327 | 326 |
return imageID |
| 328 | 327 |
} |
| 329 | 328 |
|
| ... | ... |
@@ -332,23 +318,25 @@ func TestSaveRepoWithMultipleImages(t *testing.T) {
|
| 332 | 332 |
tagBar := repoName + ":bar" |
| 333 | 333 |
|
| 334 | 334 |
idFoo := makeImage("busybox:latest", tagFoo)
|
| 335 |
+ defer deleteImages(idFoo) |
|
| 335 | 336 |
idBar := makeImage("busybox:latest", tagBar)
|
| 337 |
+ defer deleteImages(idBar) |
|
| 336 | 338 |
|
| 337 | 339 |
deleteImages(repoName) |
| 338 | 340 |
|
| 339 | 341 |
// create the archive |
| 340 |
- saveCmdFinal := fmt.Sprintf("%v save %v | tar t | grep 'VERSION' |cut -d / -f1", dockerBinary, repoName)
|
|
| 341 |
- saveCmd := exec.Command("bash", "-c", saveCmdFinal)
|
|
| 342 |
- out, _, err := runCommandWithOutput(saveCmd) |
|
| 342 |
+ out, _, err := runCommandPipelineWithOutput( |
|
| 343 |
+ exec.Command(dockerBinary, "save", repoName), |
|
| 344 |
+ exec.Command("tar", "t"),
|
|
| 345 |
+ exec.Command("grep", "VERSION"),
|
|
| 346 |
+ exec.Command("cut", "-d", "/", "-f1"))
|
|
| 343 | 347 |
if err != nil {
|
| 344 | 348 |
t.Fatalf("failed to save multiple images: %s, %v", out, err)
|
| 345 | 349 |
} |
| 346 | 350 |
actual := strings.Split(stripTrailingCharacters(out), "\n") |
| 347 | 351 |
|
| 348 | 352 |
// make the list of expected layers |
| 349 |
- historyCmdFinal := fmt.Sprintf("%v history -q --no-trunc %v", dockerBinary, "busybox:latest")
|
|
| 350 |
- historyCmd := exec.Command("bash", "-c", historyCmdFinal)
|
|
| 351 |
- out, _, err = runCommandWithOutput(historyCmd) |
|
| 353 |
+ out, _, err = runCommandWithOutput(exec.Command(dockerBinary, "history", "-q", "--no-trunc", "busybox:latest")) |
|
| 352 | 354 |
if err != nil {
|
| 353 | 355 |
t.Fatalf("failed to get history: %s, %v", out, err)
|
| 354 | 356 |
} |
| ... | ... |
@@ -3,6 +3,7 @@ package main |
| 3 | 3 |
import ( |
| 4 | 4 |
"bytes" |
| 5 | 5 |
"encoding/json" |
| 6 |
+ "errors" |
|
| 6 | 7 |
"fmt" |
| 7 | 8 |
"io" |
| 8 | 9 |
"math/rand" |
| ... | ... |
@@ -95,6 +96,40 @@ func runCommand(cmd *exec.Cmd) (exitCode int, err error) {
|
| 95 | 95 |
return |
| 96 | 96 |
} |
| 97 | 97 |
|
| 98 |
+func runCommandPipelineWithOutput(cmds ...*exec.Cmd) (output string, exitCode int, err error) {
|
|
| 99 |
+ if len(cmds) < 2 {
|
|
| 100 |
+ return "", 0, errors.New("pipeline does not have multiple cmds")
|
|
| 101 |
+ } |
|
| 102 |
+ |
|
| 103 |
+ // connect stdin of each cmd to stdout pipe of previous cmd |
|
| 104 |
+ for i, cmd := range cmds {
|
|
| 105 |
+ if i > 0 {
|
|
| 106 |
+ prevCmd := cmds[i-1] |
|
| 107 |
+ cmd.Stdin, err = prevCmd.StdoutPipe() |
|
| 108 |
+ if err != nil {
|
|
| 109 |
+ return "", 0, fmt.Errorf("cannot set stdout pipe for %s: %v", cmd.Path, err)
|
|
| 110 |
+ } |
|
| 111 |
+ } |
|
| 112 |
+ } |
|
| 113 |
+ |
|
| 114 |
+ // start all cmds except the last |
|
| 115 |
+ for _, cmd := range cmds[:len(cmds)-1] {
|
|
| 116 |
+ if err = cmd.Start(); err != nil {
|
|
| 117 |
+ return "", 0, fmt.Errorf("starting %s failed with error: %v", cmd.Path, err)
|
|
| 118 |
+ } |
|
| 119 |
+ } |
|
| 120 |
+ |
|
| 121 |
+ defer func() {
|
|
| 122 |
+ // wait all cmds except the last to release their resources |
|
| 123 |
+ for _, cmd := range cmds[:len(cmds)-1] {
|
|
| 124 |
+ cmd.Wait() |
|
| 125 |
+ } |
|
| 126 |
+ }() |
|
| 127 |
+ |
|
| 128 |
+ // wait on last cmd |
|
| 129 |
+ return runCommandWithOutput(cmds[len(cmds)-1]) |
|
| 130 |
+} |
|
| 131 |
+ |
|
| 98 | 132 |
func logDone(message string) {
|
| 99 | 133 |
fmt.Printf("[PASSED]: %s\n", message)
|
| 100 | 134 |
} |