github.com/xiaobinqt/libcompose@v1.1.0/docker/image/image.go (about) 1 package image 2 3 import ( 4 "encoding/base64" 5 "encoding/json" 6 "fmt" 7 "io" 8 "os" 9 10 "github.com/docker/distribution/reference" 11 "github.com/docker/docker/api/types" 12 "github.com/docker/docker/client" 13 "github.com/docker/docker/pkg/jsonmessage" 14 "github.com/docker/docker/pkg/term" 15 "github.com/docker/docker/registry" 16 "github.com/sirupsen/logrus" 17 "github.com/xiaobinqt/libcompose/docker/auth" 18 "golang.org/x/net/context" 19 ) 20 21 // Exists return whether or not the service image already exists 22 func Exists(ctx context.Context, clt client.ImageAPIClient, image string) (bool, error) { 23 _, err := InspectImage(ctx, clt, image) 24 if err != nil { 25 if client.IsErrNotFound(err) { 26 return false, nil 27 } 28 return false, err 29 } 30 return true, nil 31 } 32 33 // InspectImage inspect the specified image (can be a name, an id or a digest) 34 // with the specified client. 35 func InspectImage(ctx context.Context, client client.ImageAPIClient, image string) (types.ImageInspect, error) { 36 imageInspect, _, err := client.ImageInspectWithRaw(ctx, image) 37 return imageInspect, err 38 } 39 40 // RemoveImage removes the specified image (can be a name, an id or a digest) 41 // from the daemon store with the specified client. 42 func RemoveImage(ctx context.Context, client client.ImageAPIClient, image string) error { 43 _, err := client.ImageRemove(ctx, image, types.ImageRemoveOptions{}) 44 return err 45 } 46 47 // PullImage pulls the specified image (can be a name, an id or a digest) 48 // to the daemon store with the specified client. 49 func PullImage(ctx context.Context, client client.ImageAPIClient, serviceName string, authLookup auth.Lookup, image string) error { 50 fmt.Fprintf(os.Stderr, "Pulling %s (%s)...\n", serviceName, image) 51 distributionRef, err := reference.ParseNormalizedNamed(image) 52 if err != nil { 53 return err 54 } 55 56 repoInfo, err := registry.ParseRepositoryInfo(distributionRef) 57 if err != nil { 58 return err 59 } 60 61 authConfig := authLookup.Lookup(repoInfo) 62 63 // Use ConfigFile.SaveToWriter to not re-define encodeAuthToBase64 64 encodedAuth, err := encodeAuthToBase64(authConfig) 65 if err != nil { 66 return err 67 } 68 69 options := types.ImagePullOptions{ 70 RegistryAuth: encodedAuth, 71 } 72 responseBody, err := client.ImagePull(ctx, distributionRef.String(), options) 73 if err != nil { 74 logrus.Errorf("Failed to pull image %s: %v", image, err) 75 return err 76 } 77 defer responseBody.Close() 78 79 var writeBuff io.Writer = os.Stderr 80 81 outFd, isTerminalOut := term.GetFdInfo(os.Stderr) 82 83 err = jsonmessage.DisplayJSONMessagesStream(responseBody, writeBuff, outFd, isTerminalOut, nil) 84 if err != nil { 85 if jerr, ok := err.(*jsonmessage.JSONError); ok { 86 // If no error code is set, default to 1 87 if jerr.Code == 0 { 88 jerr.Code = 1 89 } 90 fmt.Fprintf(os.Stderr, "%s", writeBuff) 91 return fmt.Errorf("Status: %s, Code: %d", jerr.Message, jerr.Code) 92 } 93 } 94 return err 95 } 96 97 // encodeAuthToBase64 serializes the auth configuration as JSON base64 payload 98 func encodeAuthToBase64(authConfig types.AuthConfig) (string, error) { 99 buf, err := json.Marshal(authConfig) 100 if err != nil { 101 return "", err 102 } 103 return base64.URLEncoding.EncodeToString(buf), nil 104 }