Signed-off-by: Daniel Nephin <dnephin@docker.com>
| ... | ... |
@@ -9,21 +9,27 @@ import ( |
| 9 | 9 |
"strings" |
| 10 | 10 |
"sync" |
| 11 | 11 |
|
| 12 |
+ "context" |
|
| 13 |
+ |
|
| 14 |
+ "github.com/docker/docker/api/types" |
|
| 15 |
+ "github.com/docker/docker/client" |
|
| 16 |
+ "github.com/docker/docker/pkg/jsonmessage" |
|
| 17 |
+ "github.com/docker/docker/pkg/term" |
|
| 12 | 18 |
"github.com/pkg/errors" |
| 13 | 19 |
) |
| 14 | 20 |
|
| 15 |
-var frozenImgDir = "/docker-frozen-images" |
|
| 21 |
+const frozenImgDir = "/docker-frozen-images" |
|
| 16 | 22 |
|
| 17 | 23 |
// FrozenImagesLinux loads the frozen image set for the integration suite |
| 18 | 24 |
// If the images are not available locally it will download them |
| 19 | 25 |
// TODO: This loads whatever is in the frozen image dir, regardless of what |
| 20 | 26 |
// images were passed in. If the images need to be downloaded, then it will respect |
| 21 | 27 |
// the passed in images |
| 22 |
-func FrozenImagesLinux(dockerBinary string, images ...string) error {
|
|
| 28 |
+func FrozenImagesLinux(client client.APIClient, images ...string) error {
|
|
| 23 | 29 |
imgNS := os.Getenv("TEST_IMAGE_NAMESPACE")
|
| 24 | 30 |
var loadImages []struct{ srcName, destName string }
|
| 25 | 31 |
for _, img := range images {
|
| 26 |
- if err := exec.Command(dockerBinary, "inspect", "--type=image", img).Run(); err != nil {
|
|
| 32 |
+ if !imageExists(client, img) {
|
|
| 27 | 33 |
srcName := img |
| 28 | 34 |
// hello-world:latest gets re-tagged as hello-world:frozen |
| 29 | 35 |
// there are some tests that use hello-world:latest specifically so it pulls |
| ... | ... |
@@ -46,35 +52,41 @@ func FrozenImagesLinux(dockerBinary string, images ...string) error {
|
| 46 | 46 |
return nil |
| 47 | 47 |
} |
| 48 | 48 |
|
| 49 |
+ ctx := context.Background() |
|
| 49 | 50 |
fi, err := os.Stat(frozenImgDir) |
| 50 | 51 |
if err != nil || !fi.IsDir() {
|
| 51 | 52 |
srcImages := make([]string, 0, len(loadImages)) |
| 52 | 53 |
for _, img := range loadImages {
|
| 53 | 54 |
srcImages = append(srcImages, img.srcName) |
| 54 | 55 |
} |
| 55 |
- if err := pullImages(dockerBinary, srcImages); err != nil {
|
|
| 56 |
+ if err := pullImages(ctx, client, srcImages); err != nil {
|
|
| 56 | 57 |
return errors.Wrap(err, "error pulling image list") |
| 57 | 58 |
} |
| 58 | 59 |
} else {
|
| 59 |
- if err := loadFrozenImages(dockerBinary); err != nil {
|
|
| 60 |
+ if err := loadFrozenImages(ctx, client); err != nil {
|
|
| 60 | 61 |
return err |
| 61 | 62 |
} |
| 62 | 63 |
} |
| 63 | 64 |
|
| 64 | 65 |
for _, img := range loadImages {
|
| 65 | 66 |
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))
|
|
| 67 |
+ if err := client.ImageTag(ctx, img.srcName, img.destName); err != nil {
|
|
| 68 |
+ return errors.Wrapf(err, "failed to tag %s as %s", img.srcName, img.destName) |
|
| 68 | 69 |
} |
| 69 |
- if out, err := exec.Command(dockerBinary, "rmi", img.srcName).CombinedOutput(); err != nil {
|
|
| 70 |
- return errors.Errorf("%v: %s", err, string(out))
|
|
| 70 |
+ if _, err := client.ImageRemove(ctx, img.srcName, types.ImageRemoveOptions{}); err != nil {
|
|
| 71 |
+ return errors.Wrapf(err, "failed to remove %s", img.srcName) |
|
| 71 | 72 |
} |
| 72 | 73 |
} |
| 73 | 74 |
} |
| 74 | 75 |
return nil |
| 75 | 76 |
} |
| 76 | 77 |
|
| 77 |
-func loadFrozenImages(dockerBinary string) error {
|
|
| 78 |
+func imageExists(client client.APIClient, name string) bool {
|
|
| 79 |
+ _, _, err := client.ImageInspectWithRaw(context.Background(), name) |
|
| 80 |
+ return err == nil |
|
| 81 |
+} |
|
| 82 |
+ |
|
| 83 |
+func loadFrozenImages(ctx context.Context, client client.APIClient) error {
|
|
| 78 | 84 |
tar, err := exec.LookPath("tar")
|
| 79 | 85 |
if err != nil {
|
| 80 | 86 |
return errors.Wrap(err, "could not find tar binary") |
| ... | ... |
@@ -90,15 +102,16 @@ func loadFrozenImages(dockerBinary string) error {
|
| 90 | 90 |
tarCmd.Start() |
| 91 | 91 |
defer tarCmd.Wait() |
| 92 | 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))
|
|
| 93 |
+ resp, err := client.ImageLoad(ctx, out, true) |
|
| 94 |
+ if err != nil {
|
|
| 95 |
+ return errors.Wrap(err, "failed to load frozen images") |
|
| 97 | 96 |
} |
| 98 |
- return nil |
|
| 97 |
+ defer resp.Body.Close() |
|
| 98 |
+ fd, isTerminal := term.GetFdInfo(os.Stdout) |
|
| 99 |
+ return jsonmessage.DisplayJSONMessagesStream(resp.Body, os.Stdout, fd, isTerminal, nil) |
|
| 99 | 100 |
} |
| 100 | 101 |
|
| 101 |
-func pullImages(dockerBinary string, images []string) error {
|
|
| 102 |
+func pullImages(ctx context.Context, client client.APIClient, images []string) error {
|
|
| 102 | 103 |
cwd, err := os.Getwd() |
| 103 | 104 |
if err != nil {
|
| 104 | 105 |
return errors.Wrap(err, "error getting path to dockerfile") |
| ... | ... |
@@ -119,16 +132,8 @@ func pullImages(dockerBinary string, images []string) error {
|
| 119 | 119 |
wg.Add(1) |
| 120 | 120 |
go func(tag, ref string) {
|
| 121 | 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)
|
|
| 122 |
+ if err := pullTagAndRemove(ctx, client, ref, tag); err != nil {
|
|
| 123 |
+ chErr <- err |
|
| 132 | 124 |
return |
| 133 | 125 |
} |
| 134 | 126 |
}(tag, ref) |
| ... | ... |
@@ -138,6 +143,25 @@ func pullImages(dockerBinary string, images []string) error {
|
| 138 | 138 |
return <-chErr |
| 139 | 139 |
} |
| 140 | 140 |
|
| 141 |
+func pullTagAndRemove(ctx context.Context, client client.APIClient, ref string, tag string) error {
|
|
| 142 |
+ resp, err := client.ImagePull(ctx, ref, types.ImagePullOptions{})
|
|
| 143 |
+ if err != nil {
|
|
| 144 |
+ return errors.Wrapf(err, "failed to pull %s", ref) |
|
| 145 |
+ } |
|
| 146 |
+ defer resp.Close() |
|
| 147 |
+ fd, isTerminal := term.GetFdInfo(os.Stdout) |
|
| 148 |
+ if err := jsonmessage.DisplayJSONMessagesStream(resp, os.Stdout, fd, isTerminal, nil); err != nil {
|
|
| 149 |
+ return err |
|
| 150 |
+ } |
|
| 151 |
+ |
|
| 152 |
+ if err := client.ImageTag(ctx, ref, tag); err != nil {
|
|
| 153 |
+ return errors.Wrapf(err, "failed to tag %s as %s", ref, tag) |
|
| 154 |
+ } |
|
| 155 |
+ _, err = client.ImageRemove(ctx, ref, types.ImageRemoveOptions{})
|
|
| 156 |
+ return errors.Wrapf(err, "failed to remove %s", ref) |
|
| 157 |
+ |
|
| 158 |
+} |
|
| 159 |
+ |
|
| 141 | 160 |
func readFrozenImageList(dockerfilePath string, images []string) (map[string]string, error) {
|
| 142 | 161 |
f, err := os.Open(dockerfilePath) |
| 143 | 162 |
if err != nil {
|
| ... | ... |
@@ -156,11 +180,6 @@ func readFrozenImageList(dockerfilePath string, images []string) (map[string]str |
| 156 | 156 |
continue |
| 157 | 157 |
} |
| 158 | 158 |
|
| 159 |
- frozenImgDir = line[2] |
|
| 160 |
- if line[2] == frozenImgDir {
|
|
| 161 |
- frozenImgDir = filepath.Join(os.Getenv("DEST"), "frozen-images")
|
|
| 162 |
- } |
|
| 163 |
- |
|
| 164 | 159 |
for scanner.Scan() {
|
| 165 | 160 |
img := strings.TrimSpace(scanner.Text()) |
| 166 | 161 |
img = strings.TrimSuffix(img, "\\") |