github.com/zhuohuang-hust/src-cbuild@v0.0.0-20230105071821-c7aab3e7c840/daemon/image_pull.go (about)

     1  package daemon
     2  
     3  import (
     4  	"io"
     5  	"strings"
     6  
     7  	dist "github.com/docker/distribution"
     8  	"github.com/docker/distribution/digest"
     9  	"github.com/docker/docker/api/types"
    10  	"github.com/docker/docker/builder"
    11  	"github.com/docker/docker/distribution"
    12  	"github.com/docker/docker/pkg/progress"
    13  	"github.com/docker/docker/reference"
    14  	"github.com/docker/docker/registry"
    15  	"golang.org/x/net/context"
    16  )
    17  
    18  // PullImage initiates a pull operation. image is the repository name to pull, and
    19  // tag may be either empty, or indicate a specific tag to pull.
    20  func (daemon *Daemon) PullImage(ctx context.Context, image, tag string, metaHeaders map[string][]string, authConfig *types.AuthConfig, outStream io.Writer) error {
    21  	// Special case: "pull -a" may send an image name with a
    22  	// trailing :. This is ugly, but let's not break API
    23  	// compatibility.
    24  	image = strings.TrimSuffix(image, ":")
    25  
    26  	ref, err := reference.ParseNamed(image)
    27  	if err != nil {
    28  		return err
    29  	}
    30  
    31  	if tag != "" {
    32  		// The "tag" could actually be a digest.
    33  		var dgst digest.Digest
    34  		dgst, err = digest.ParseDigest(tag)
    35  		if err == nil {
    36  			ref, err = reference.WithDigest(reference.TrimNamed(ref), dgst)
    37  		} else {
    38  			ref, err = reference.WithTag(ref, tag)
    39  		}
    40  		if err != nil {
    41  			return err
    42  		}
    43  	}
    44  
    45  	return daemon.pullImageWithReference(ctx, ref, metaHeaders, authConfig, outStream)
    46  }
    47  
    48  // PullOnBuild tells Docker to pull image referenced by `name`.
    49  func (daemon *Daemon) PullOnBuild(ctx context.Context, name string, authConfigs map[string]types.AuthConfig, output io.Writer) (builder.Image, error) {
    50  	ref, err := reference.ParseNamed(name)
    51  	if err != nil {
    52  		return nil, err
    53  	}
    54  	ref = reference.WithDefaultTag(ref)
    55  
    56  	pullRegistryAuth := &types.AuthConfig{}
    57  	if len(authConfigs) > 0 {
    58  		// The request came with a full auth config file, we prefer to use that
    59  		repoInfo, err := daemon.RegistryService.ResolveRepository(ref)
    60  		if err != nil {
    61  			return nil, err
    62  		}
    63  
    64  		resolvedConfig := registry.ResolveAuthConfig(
    65  			authConfigs,
    66  			repoInfo.Index,
    67  		)
    68  		pullRegistryAuth = &resolvedConfig
    69  	}
    70  
    71  	if err := daemon.pullImageWithReference(ctx, ref, nil, pullRegistryAuth, output); err != nil {
    72  		return nil, err
    73  	}
    74  	return daemon.GetImage(name)
    75  }
    76  
    77  func (daemon *Daemon) pullImageWithReference(ctx context.Context, ref reference.Named, metaHeaders map[string][]string, authConfig *types.AuthConfig, outStream io.Writer) error {
    78  	// Include a buffer so that slow client connections don't affect
    79  	// transfer performance.
    80  	progressChan := make(chan progress.Progress, 100)
    81  
    82  	writesDone := make(chan struct{})
    83  
    84  	ctx, cancelFunc := context.WithCancel(ctx)
    85  
    86  	go func() {
    87  		writeDistributionProgress(cancelFunc, outStream, progressChan)
    88  		close(writesDone)
    89  	}()
    90  
    91  	imagePullConfig := &distribution.ImagePullConfig{
    92  		MetaHeaders:      metaHeaders,
    93  		AuthConfig:       authConfig,
    94  		ProgressOutput:   progress.ChanOutput(progressChan),
    95  		RegistryService:  daemon.RegistryService,
    96  		ImageEventLogger: daemon.LogImageEvent,
    97  		MetadataStore:    daemon.distributionMetadataStore,
    98  		ImageStore:       daemon.imageStore,
    99  		ReferenceStore:   daemon.referenceStore,
   100  		DownloadManager:  daemon.downloadManager,
   101  	}
   102  
   103  	err := distribution.Pull(ctx, ref, imagePullConfig)
   104  	close(progressChan)
   105  	<-writesDone
   106  	return err
   107  }
   108  
   109  // GetRepository returns a repository from the registry.
   110  func (daemon *Daemon) GetRepository(ctx context.Context, ref reference.NamedTagged, authConfig *types.AuthConfig) (dist.Repository, bool, error) {
   111  	// get repository info
   112  	repoInfo, err := daemon.RegistryService.ResolveRepository(ref)
   113  	if err != nil {
   114  		return nil, false, err
   115  	}
   116  	// makes sure name is not empty or `scratch`
   117  	if err := distribution.ValidateRepoName(repoInfo.Name()); err != nil {
   118  		return nil, false, err
   119  	}
   120  
   121  	// get endpoints
   122  	endpoints, err := daemon.RegistryService.LookupPullEndpoints(repoInfo.Hostname())
   123  	if err != nil {
   124  		return nil, false, err
   125  	}
   126  
   127  	// retrieve repository
   128  	var (
   129  		confirmedV2 bool
   130  		repository  dist.Repository
   131  		lastError   error
   132  	)
   133  
   134  	for _, endpoint := range endpoints {
   135  		if endpoint.Version == registry.APIVersion1 {
   136  			continue
   137  		}
   138  
   139  		repository, confirmedV2, lastError = distribution.NewV2Repository(ctx, repoInfo, endpoint, nil, authConfig, "pull")
   140  		if lastError == nil && confirmedV2 {
   141  			break
   142  		}
   143  	}
   144  	return repository, confirmedV2, lastError
   145  }