github.com/guilhermebr/docker@v1.4.2-0.20150428121140-67da055cebca/integration-cli/docker_cli_save_load_test.go (about) 1 package main 2 3 import ( 4 "fmt" 5 "io/ioutil" 6 "os" 7 "os/exec" 8 "path/filepath" 9 "reflect" 10 "sort" 11 "strings" 12 13 "github.com/go-check/check" 14 ) 15 16 // save a repo using gz compression and try to load it using stdout 17 func (s *DockerSuite) TestSaveXzAndLoadRepoStdout(c *check.C) { 18 runCmd := exec.Command(dockerBinary, "run", "-d", "busybox", "true") 19 out, _, err := runCommandWithOutput(runCmd) 20 if err != nil { 21 c.Fatalf("failed to create a container: %v %v", out, err) 22 } 23 24 cleanedContainerID := strings.TrimSpace(out) 25 26 repoName := "foobar-save-load-test-xz-gz" 27 28 inspectCmd := exec.Command(dockerBinary, "inspect", cleanedContainerID) 29 out, _, err = runCommandWithOutput(inspectCmd) 30 if err != nil { 31 c.Fatalf("output should've been a container id: %v %v", cleanedContainerID, err) 32 } 33 34 commitCmd := exec.Command(dockerBinary, "commit", cleanedContainerID, repoName) 35 out, _, err = runCommandWithOutput(commitCmd) 36 if err != nil { 37 c.Fatalf("failed to commit container: %v %v", out, err) 38 } 39 40 inspectCmd = exec.Command(dockerBinary, "inspect", repoName) 41 before, _, err := runCommandWithOutput(inspectCmd) 42 if err != nil { 43 c.Fatalf("the repo should exist before saving it: %v %v", before, err) 44 } 45 46 repoTarball, _, err := runCommandPipelineWithOutput( 47 exec.Command(dockerBinary, "save", repoName), 48 exec.Command("xz", "-c"), 49 exec.Command("gzip", "-c")) 50 if err != nil { 51 c.Fatalf("failed to save repo: %v %v", out, err) 52 } 53 deleteImages(repoName) 54 55 loadCmd := exec.Command(dockerBinary, "load") 56 loadCmd.Stdin = strings.NewReader(repoTarball) 57 out, _, err = runCommandWithOutput(loadCmd) 58 if err == nil { 59 c.Fatalf("expected error, but succeeded with no error and output: %v", out) 60 } 61 62 inspectCmd = exec.Command(dockerBinary, "inspect", repoName) 63 after, _, err := runCommandWithOutput(inspectCmd) 64 if err == nil { 65 c.Fatalf("the repo should not exist: %v", after) 66 } 67 68 deleteImages(repoName) 69 70 } 71 72 // save a repo using xz+gz compression and try to load it using stdout 73 func (s *DockerSuite) TestSaveXzGzAndLoadRepoStdout(c *check.C) { 74 runCmd := exec.Command(dockerBinary, "run", "-d", "busybox", "true") 75 out, _, err := runCommandWithOutput(runCmd) 76 if err != nil { 77 c.Fatalf("failed to create a container: %v %v", out, err) 78 } 79 80 cleanedContainerID := strings.TrimSpace(out) 81 82 repoName := "foobar-save-load-test-xz-gz" 83 84 inspectCmd := exec.Command(dockerBinary, "inspect", cleanedContainerID) 85 out, _, err = runCommandWithOutput(inspectCmd) 86 if err != nil { 87 c.Fatalf("output should've been a container id: %v %v", cleanedContainerID, err) 88 } 89 90 commitCmd := exec.Command(dockerBinary, "commit", cleanedContainerID, repoName) 91 out, _, err = runCommandWithOutput(commitCmd) 92 if err != nil { 93 c.Fatalf("failed to commit container: %v %v", out, err) 94 } 95 96 inspectCmd = exec.Command(dockerBinary, "inspect", repoName) 97 before, _, err := runCommandWithOutput(inspectCmd) 98 if err != nil { 99 c.Fatalf("the repo should exist before saving it: %v %v", before, err) 100 } 101 102 out, _, err = runCommandPipelineWithOutput( 103 exec.Command(dockerBinary, "save", repoName), 104 exec.Command("xz", "-c"), 105 exec.Command("gzip", "-c")) 106 if err != nil { 107 c.Fatalf("failed to save repo: %v %v", out, err) 108 } 109 110 deleteImages(repoName) 111 112 loadCmd := exec.Command(dockerBinary, "load") 113 loadCmd.Stdin = strings.NewReader(out) 114 out, _, err = runCommandWithOutput(loadCmd) 115 if err == nil { 116 c.Fatalf("expected error, but succeeded with no error and output: %v", out) 117 } 118 119 inspectCmd = exec.Command(dockerBinary, "inspect", repoName) 120 after, _, err := runCommandWithOutput(inspectCmd) 121 if err == nil { 122 c.Fatalf("the repo should not exist: %v", after) 123 } 124 125 deleteContainer(cleanedContainerID) 126 deleteImages(repoName) 127 128 } 129 130 func (s *DockerSuite) TestSaveSingleTag(c *check.C) { 131 repoName := "foobar-save-single-tag-test" 132 133 tagCmd := exec.Command(dockerBinary, "tag", "busybox:latest", fmt.Sprintf("%v:latest", repoName)) 134 if out, _, err := runCommandWithOutput(tagCmd); err != nil { 135 c.Fatalf("failed to tag repo: %s, %v", out, err) 136 } 137 138 idCmd := exec.Command(dockerBinary, "images", "-q", "--no-trunc", repoName) 139 out, _, err := runCommandWithOutput(idCmd) 140 if err != nil { 141 c.Fatalf("failed to get repo ID: %s, %v", out, err) 142 } 143 cleanedImageID := strings.TrimSpace(out) 144 145 out, _, err = runCommandPipelineWithOutput( 146 exec.Command(dockerBinary, "save", fmt.Sprintf("%v:latest", repoName)), 147 exec.Command("tar", "t"), 148 exec.Command("grep", "-E", fmt.Sprintf("(^repositories$|%v)", cleanedImageID))) 149 if err != nil { 150 c.Fatalf("failed to save repo with image ID and 'repositories' file: %s, %v", out, err) 151 } 152 153 } 154 155 func (s *DockerSuite) TestSaveImageId(c *check.C) { 156 repoName := "foobar-save-image-id-test" 157 158 tagCmd := exec.Command(dockerBinary, "tag", "emptyfs:latest", fmt.Sprintf("%v:latest", repoName)) 159 if out, _, err := runCommandWithOutput(tagCmd); err != nil { 160 c.Fatalf("failed to tag repo: %s, %v", out, err) 161 } 162 163 idLongCmd := exec.Command(dockerBinary, "images", "-q", "--no-trunc", repoName) 164 out, _, err := runCommandWithOutput(idLongCmd) 165 if err != nil { 166 c.Fatalf("failed to get repo ID: %s, %v", out, err) 167 } 168 169 cleanedLongImageID := strings.TrimSpace(out) 170 171 idShortCmd := exec.Command(dockerBinary, "images", "-q", repoName) 172 out, _, err = runCommandWithOutput(idShortCmd) 173 if err != nil { 174 c.Fatalf("failed to get repo short ID: %s, %v", out, err) 175 } 176 177 cleanedShortImageID := strings.TrimSpace(out) 178 179 saveCmd := exec.Command(dockerBinary, "save", cleanedShortImageID) 180 tarCmd := exec.Command("tar", "t") 181 tarCmd.Stdin, err = saveCmd.StdoutPipe() 182 if err != nil { 183 c.Fatalf("cannot set stdout pipe for tar: %v", err) 184 } 185 grepCmd := exec.Command("grep", cleanedLongImageID) 186 grepCmd.Stdin, err = tarCmd.StdoutPipe() 187 if err != nil { 188 c.Fatalf("cannot set stdout pipe for grep: %v", err) 189 } 190 191 if err = tarCmd.Start(); err != nil { 192 c.Fatalf("tar failed with error: %v", err) 193 } 194 if err = saveCmd.Start(); err != nil { 195 c.Fatalf("docker save failed with error: %v", err) 196 } 197 defer saveCmd.Wait() 198 defer tarCmd.Wait() 199 200 out, _, err = runCommandWithOutput(grepCmd) 201 202 if err != nil { 203 c.Fatalf("failed to save repo with image ID: %s, %v", out, err) 204 } 205 206 } 207 208 // save a repo and try to load it using flags 209 func (s *DockerSuite) TestSaveAndLoadRepoFlags(c *check.C) { 210 runCmd := exec.Command(dockerBinary, "run", "-d", "busybox", "true") 211 out, _, err := runCommandWithOutput(runCmd) 212 if err != nil { 213 c.Fatalf("failed to create a container: %s, %v", out, err) 214 } 215 216 cleanedContainerID := strings.TrimSpace(out) 217 218 repoName := "foobar-save-load-test" 219 220 inspectCmd := exec.Command(dockerBinary, "inspect", cleanedContainerID) 221 if out, _, err = runCommandWithOutput(inspectCmd); err != nil { 222 c.Fatalf("output should've been a container id: %s, %v", out, err) 223 } 224 225 commitCmd := exec.Command(dockerBinary, "commit", cleanedContainerID, repoName) 226 deleteImages(repoName) 227 if out, _, err = runCommandWithOutput(commitCmd); err != nil { 228 c.Fatalf("failed to commit container: %s, %v", out, err) 229 } 230 231 inspectCmd = exec.Command(dockerBinary, "inspect", repoName) 232 before, _, err := runCommandWithOutput(inspectCmd) 233 if err != nil { 234 c.Fatalf("the repo should exist before saving it: %s, %v", before, err) 235 236 } 237 238 out, _, err = runCommandPipelineWithOutput( 239 exec.Command(dockerBinary, "save", repoName), 240 exec.Command(dockerBinary, "load")) 241 if err != nil { 242 c.Fatalf("failed to save and load repo: %s, %v", out, err) 243 } 244 245 inspectCmd = exec.Command(dockerBinary, "inspect", repoName) 246 after, _, err := runCommandWithOutput(inspectCmd) 247 if err != nil { 248 c.Fatalf("the repo should exist after loading it: %s, %v", after, err) 249 } 250 251 if before != after { 252 c.Fatalf("inspect is not the same after a save / load") 253 } 254 255 } 256 257 func (s *DockerSuite) TestSaveMultipleNames(c *check.C) { 258 repoName := "foobar-save-multi-name-test" 259 260 // Make one image 261 tagCmd := exec.Command(dockerBinary, "tag", "emptyfs:latest", fmt.Sprintf("%v-one:latest", repoName)) 262 if out, _, err := runCommandWithOutput(tagCmd); err != nil { 263 c.Fatalf("failed to tag repo: %s, %v", out, err) 264 } 265 266 // Make two images 267 tagCmd = exec.Command(dockerBinary, "tag", "emptyfs:latest", fmt.Sprintf("%v-two:latest", repoName)) 268 out, _, err := runCommandWithOutput(tagCmd) 269 if err != nil { 270 c.Fatalf("failed to tag repo: %s, %v", out, err) 271 } 272 273 out, _, err = runCommandPipelineWithOutput( 274 exec.Command(dockerBinary, "save", fmt.Sprintf("%v-one", repoName), fmt.Sprintf("%v-two:latest", repoName)), 275 exec.Command("tar", "xO", "repositories"), 276 exec.Command("grep", "-q", "-E", "(-one|-two)"), 277 ) 278 if err != nil { 279 c.Fatalf("failed to save multiple repos: %s, %v", out, err) 280 } 281 282 } 283 284 func (s *DockerSuite) TestSaveRepoWithMultipleImages(c *check.C) { 285 286 makeImage := func(from string, tag string) string { 287 runCmd := exec.Command(dockerBinary, "run", "-d", from, "true") 288 var ( 289 out string 290 err error 291 ) 292 if out, _, err = runCommandWithOutput(runCmd); err != nil { 293 c.Fatalf("failed to create a container: %v %v", out, err) 294 } 295 cleanedContainerID := strings.TrimSpace(out) 296 297 commitCmd := exec.Command(dockerBinary, "commit", cleanedContainerID, tag) 298 if out, _, err = runCommandWithOutput(commitCmd); err != nil { 299 c.Fatalf("failed to commit container: %v %v", out, err) 300 } 301 imageID := strings.TrimSpace(out) 302 return imageID 303 } 304 305 repoName := "foobar-save-multi-images-test" 306 tagFoo := repoName + ":foo" 307 tagBar := repoName + ":bar" 308 309 idFoo := makeImage("busybox:latest", tagFoo) 310 idBar := makeImage("busybox:latest", tagBar) 311 312 deleteImages(repoName) 313 314 // create the archive 315 out, _, err := runCommandPipelineWithOutput( 316 exec.Command(dockerBinary, "save", repoName), 317 exec.Command("tar", "t"), 318 exec.Command("grep", "VERSION"), 319 exec.Command("cut", "-d", "/", "-f1")) 320 if err != nil { 321 c.Fatalf("failed to save multiple images: %s, %v", out, err) 322 } 323 actual := strings.Split(strings.TrimSpace(out), "\n") 324 325 // make the list of expected layers 326 out, _, err = runCommandWithOutput(exec.Command(dockerBinary, "history", "-q", "--no-trunc", "busybox:latest")) 327 if err != nil { 328 c.Fatalf("failed to get history: %s, %v", out, err) 329 } 330 331 expected := append(strings.Split(strings.TrimSpace(out), "\n"), idFoo, idBar) 332 333 sort.Strings(actual) 334 sort.Strings(expected) 335 if !reflect.DeepEqual(expected, actual) { 336 c.Fatalf("archive does not contains the right layers: got %v, expected %v", actual, expected) 337 } 338 339 } 340 341 // Issue #6722 #5892 ensure directories are included in changes 342 func (s *DockerSuite) TestSaveDirectoryPermissions(c *check.C) { 343 layerEntries := []string{"opt/", "opt/a/", "opt/a/b/", "opt/a/b/c"} 344 layerEntriesAUFS := []string{"./", ".wh..wh.aufs", ".wh..wh.orph/", ".wh..wh.plnk/", "opt/", "opt/a/", "opt/a/b/", "opt/a/b/c"} 345 346 name := "save-directory-permissions" 347 tmpDir, err := ioutil.TempDir("", "save-layers-with-directories") 348 if err != nil { 349 c.Errorf("failed to create temporary directory: %s", err) 350 } 351 extractionDirectory := filepath.Join(tmpDir, "image-extraction-dir") 352 os.Mkdir(extractionDirectory, 0777) 353 354 defer os.RemoveAll(tmpDir) 355 _, err = buildImage(name, 356 `FROM busybox 357 RUN adduser -D user && mkdir -p /opt/a/b && chown -R user:user /opt/a 358 RUN touch /opt/a/b/c && chown user:user /opt/a/b/c`, 359 true) 360 if err != nil { 361 c.Fatal(err) 362 } 363 364 if out, _, err := runCommandPipelineWithOutput( 365 exec.Command(dockerBinary, "save", name), 366 exec.Command("tar", "-xf", "-", "-C", extractionDirectory), 367 ); err != nil { 368 c.Errorf("failed to save and extract image: %s", out) 369 } 370 371 dirs, err := ioutil.ReadDir(extractionDirectory) 372 if err != nil { 373 c.Errorf("failed to get a listing of the layer directories: %s", err) 374 } 375 376 found := false 377 for _, entry := range dirs { 378 var entriesSansDev []string 379 if entry.IsDir() { 380 layerPath := filepath.Join(extractionDirectory, entry.Name(), "layer.tar") 381 382 f, err := os.Open(layerPath) 383 if err != nil { 384 c.Fatalf("failed to open %s: %s", layerPath, err) 385 } 386 387 entries, err := ListTar(f) 388 for _, e := range entries { 389 if !strings.Contains(e, "dev/") { 390 entriesSansDev = append(entriesSansDev, e) 391 } 392 } 393 if err != nil { 394 c.Fatalf("encountered error while listing tar entries: %s", err) 395 } 396 397 if reflect.DeepEqual(entriesSansDev, layerEntries) || reflect.DeepEqual(entriesSansDev, layerEntriesAUFS) { 398 found = true 399 break 400 } 401 } 402 } 403 404 if !found { 405 c.Fatalf("failed to find the layer with the right content listing") 406 } 407 408 }