gitee.com/bomy/docker.git@v1.13.1/integration-cli/fixtures/load/frozen.go (about) 1 package load 2 3 import ( 4 "bufio" 5 "bytes" 6 "os" 7 "os/exec" 8 "path/filepath" 9 "strings" 10 "sync" 11 12 "github.com/pkg/errors" 13 ) 14 15 var frozenImgDir = "/docker-frozen-images" 16 17 // FrozenImagesLinux loads the frozen image set for the integration suite 18 // If the images are not available locally it will download them 19 // TODO: This loads whatever is in the frozen image dir, regardless of what 20 // images were passed in. If the images need to be downloaded, then it will respect 21 // the passed in images 22 func FrozenImagesLinux(dockerBinary string, images ...string) error { 23 imgNS := os.Getenv("TEST_IMAGE_NAMESPACE") 24 var loadImages []struct{ srcName, destName string } 25 for _, img := range images { 26 if err := exec.Command(dockerBinary, "inspect", "--type=image", img).Run(); err != nil { 27 srcName := img 28 // hello-world:latest gets re-tagged as hello-world:frozen 29 // there are some tests that use hello-world:latest specifically so it pulls 30 // the image and hello-world:frozen is used for when we just want a super 31 // small image 32 if img == "hello-world:frozen" { 33 srcName = "hello-world:latest" 34 } 35 if imgNS != "" { 36 srcName = imgNS + "/" + srcName 37 } 38 loadImages = append(loadImages, struct{ srcName, destName string }{ 39 srcName: srcName, 40 destName: img, 41 }) 42 } 43 } 44 if len(loadImages) == 0 { 45 // everything is loaded, we're done 46 return nil 47 } 48 49 fi, err := os.Stat(frozenImgDir) 50 if err != nil || !fi.IsDir() { 51 srcImages := make([]string, 0, len(loadImages)) 52 for _, img := range loadImages { 53 srcImages = append(srcImages, img.srcName) 54 } 55 if err := pullImages(dockerBinary, srcImages); err != nil { 56 return errors.Wrap(err, "error pulling image list") 57 } 58 } else { 59 if err := loadFrozenImages(dockerBinary); err != nil { 60 return err 61 } 62 } 63 64 for _, img := range loadImages { 65 if img.srcName != img.destName { 66 if out, err := exec.Command(dockerBinary, "tag", img.srcName, img.destName).CombinedOutput(); err != nil { 67 return errors.Errorf("%v: %s", err, string(out)) 68 } 69 if out, err := exec.Command(dockerBinary, "rmi", img.srcName).CombinedOutput(); err != nil { 70 return errors.Errorf("%v: %s", err, string(out)) 71 } 72 } 73 } 74 return nil 75 } 76 77 func loadFrozenImages(dockerBinary string) error { 78 tar, err := exec.LookPath("tar") 79 if err != nil { 80 return errors.Wrap(err, "could not find tar binary") 81 } 82 tarCmd := exec.Command(tar, "-cC", frozenImgDir, ".") 83 out, err := tarCmd.StdoutPipe() 84 if err != nil { 85 return errors.Wrap(err, "error getting stdout pipe for tar command") 86 } 87 88 errBuf := bytes.NewBuffer(nil) 89 tarCmd.Stderr = errBuf 90 tarCmd.Start() 91 defer tarCmd.Wait() 92 93 cmd := exec.Command(dockerBinary, "load") 94 cmd.Stdin = out 95 if out, err := cmd.CombinedOutput(); err != nil { 96 return errors.Errorf("%v: %s", err, string(out)) 97 } 98 return nil 99 } 100 101 func pullImages(dockerBinary string, images []string) error { 102 cwd, err := os.Getwd() 103 if err != nil { 104 return errors.Wrap(err, "error getting path to dockerfile") 105 } 106 dockerfile := os.Getenv("DOCKERFILE") 107 if dockerfile == "" { 108 dockerfile = "Dockerfile" 109 } 110 dockerfilePath := filepath.Join(filepath.Dir(filepath.Clean(cwd)), dockerfile) 111 pullRefs, err := readFrozenImageList(dockerfilePath, images) 112 if err != nil { 113 return errors.Wrap(err, "error reading frozen image list") 114 } 115 116 var wg sync.WaitGroup 117 chErr := make(chan error, len(images)) 118 for tag, ref := range pullRefs { 119 wg.Add(1) 120 go func(tag, ref string) { 121 defer wg.Done() 122 if out, err := exec.Command(dockerBinary, "pull", ref).CombinedOutput(); err != nil { 123 chErr <- errors.Errorf("%v: %s", string(out), err) 124 return 125 } 126 if out, err := exec.Command(dockerBinary, "tag", ref, tag).CombinedOutput(); err != nil { 127 chErr <- errors.Errorf("%v: %s", string(out), err) 128 return 129 } 130 if out, err := exec.Command(dockerBinary, "rmi", ref).CombinedOutput(); err != nil { 131 chErr <- errors.Errorf("%v: %s", string(out), err) 132 return 133 } 134 }(tag, ref) 135 } 136 wg.Wait() 137 close(chErr) 138 return <-chErr 139 } 140 141 func readFrozenImageList(dockerfilePath string, images []string) (map[string]string, error) { 142 f, err := os.Open(dockerfilePath) 143 if err != nil { 144 return nil, errors.Wrap(err, "error reading dockerfile") 145 } 146 defer f.Close() 147 ls := make(map[string]string) 148 149 scanner := bufio.NewScanner(f) 150 for scanner.Scan() { 151 line := strings.Fields(scanner.Text()) 152 if len(line) < 3 { 153 continue 154 } 155 if !(line[0] == "RUN" && line[1] == "./contrib/download-frozen-image-v2.sh") { 156 continue 157 } 158 159 frozenImgDir = line[2] 160 if line[2] == frozenImgDir { 161 frozenImgDir = filepath.Join(os.Getenv("DEST"), "frozen-images") 162 } 163 164 for scanner.Scan() { 165 img := strings.TrimSpace(scanner.Text()) 166 img = strings.TrimSuffix(img, "\\") 167 img = strings.TrimSpace(img) 168 split := strings.Split(img, "@") 169 if len(split) < 2 { 170 break 171 } 172 173 for _, i := range images { 174 if split[0] == i { 175 ls[i] = img 176 break 177 } 178 } 179 } 180 } 181 return ls, nil 182 }