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  }