Exemple #1
0
// CmdPull pulls an image or a repository from the registry.
//
// Usage: docker pull [OPTIONS] IMAGENAME[:TAG|@DIGEST]
func (cli *DockerCli) CmdPull(args ...string) error {
	cmd := Cli.Subcmd("pull", []string{"NAME[:TAG|@DIGEST]"}, Cli.DockerCommands["pull"].Description, true)
	allTags := cmd.Bool([]string{"a", "-all-tags"}, false, "Download all tagged images in the repository")
	cmd.Require(flag.Exact, 1)

	cmd.ParseFlags(args, true)
	remote := cmd.Arg(0)

	distributionRef, err := reference.ParseNamed(remote)
	if err != nil {
		return err
	}
	if *allTags && !reference.IsNameOnly(distributionRef) {
		return errors.New("tag can't be used with --all-tags/-a")
	}

	if !*allTags && reference.IsNameOnly(distributionRef) {
		distributionRef = reference.WithDefaultTag(distributionRef)
		fmt.Fprintf(cli.out, "Using default tag: %s\n", reference.DefaultTag)
	}

	// Resolve the Repository name from fqn to RepositoryInfo
	repoInfo, err := registry.ParseRepositoryInfo(distributionRef)
	if err != nil {
		return err
	}

	authConfig := cli.resolveAuthConfig(repoInfo.Index)
	requestPrivilege := cli.registryAuthenticationPrivilegedFunc(repoInfo.Index, "pull")

	return cli.imagePullPrivileged(authConfig, distributionRef.String(), "", requestPrivilege)
}
Exemple #2
0
// Pull tells Docker to pull image referenced by `name`.
func (d Docker) Pull(name string) (builder.Image, error) {
	ref, err := reference.ParseNamed(name)
	if err != nil {
		return nil, err
	}
	ref = reference.WithDefaultTag(ref)

	pullRegistryAuth := &types.AuthConfig{}
	if len(d.AuthConfigs) > 0 {
		// The request came with a full auth config file, we prefer to use that
		repoInfo, err := d.Daemon.RegistryService.ResolveRepository(ref)
		if err != nil {
			return nil, err
		}

		resolvedConfig := registry.ResolveAuthConfig(
			d.AuthConfigs,
			repoInfo.Index,
		)
		pullRegistryAuth = &resolvedConfig
	}

	if err := d.Daemon.PullImage(ref, nil, pullRegistryAuth, ioutils.NopWriteCloser(d.OutOld)); err != nil {
		return nil, err
	}
	return d.GetImage(name)
}
func runInstall(dockerCli *client.DockerCli, opts pluginOptions) error {
	named, err := reference.ParseNamed(opts.name) // FIXME: validate
	if err != nil {
		return err
	}
	named = reference.WithDefaultTag(named)
	ref, ok := named.(reference.NamedTagged)
	if !ok {
		return fmt.Errorf("invalid name: %s", named.String())
	}

	ctx := context.Background()

	repoInfo, err := registry.ParseRepositoryInfo(named)
	authConfig := dockerCli.ResolveAuthConfig(ctx, repoInfo.Index)

	encodedAuth, err := client.EncodeAuthToBase64(authConfig)
	if err != nil {
		return err
	}

	requestPrivilege := dockerCli.RegistryAuthenticationPrivilegedFunc(repoInfo.Index, "plugin install")

	// TODO: pass acceptAllPermissions and noEnable flag
	options := types.PluginInstallOptions{
		RegistryAuth:          encodedAuth,
		Disabled:              false,
		AcceptAllPermissions:  opts.grantPerms,
		AcceptPermissionsFunc: acceptPrivileges(dockerCli, opts.name),
		PrivilegeFunc:         requestPrivilege,
	}

	return dockerCli.Client().PluginInstall(ctx, ref.String(), options)
}
Exemple #4
0
// PullOnBuild tells Docker to pull image referenced by `name`.
func (daemon *Daemon) PullOnBuild(ctx context.Context, name string, authConfigs map[string]types.AuthConfig, output io.Writer) (builder.Image, error) {
	ref, err := reference.ParseNamed(name)
	if err != nil {
		return nil, err
	}
	ref = reference.WithDefaultTag(ref)

	pullRegistryAuth := &types.AuthConfig{}
	if len(authConfigs) > 0 {
		// The request came with a full auth config file, we prefer to use that
		repoInfo, err := daemon.RegistryService.ResolveRepository(ref)
		if err != nil {
			return nil, err
		}

		resolvedConfig := registry.ResolveAuthConfig(
			authConfigs,
			repoInfo.Index,
		)
		pullRegistryAuth = &resolvedConfig
	}

	if err := daemon.pullImageWithReference(ctx, ref, nil, pullRegistryAuth, output); err != nil {
		return nil, err
	}
	return daemon.GetImage(name)
}
Exemple #5
0
// sanitizeRepoAndTags parses the raw "t" parameter received from the client
// to a slice of repoAndTag.
// It also validates each repoName and tag.
func sanitizeRepoAndTags(names []string) ([]reference.Named, error) {
	var (
		repoAndTags []reference.Named
		// This map is used for deduplicating the "-t" parameter.
		uniqNames = make(map[string]struct{})
	)
	for _, repo := range names {
		if repo == "" {
			continue
		}

		ref, err := reference.ParseNamed(repo)
		if err != nil {
			return nil, err
		}

		ref = reference.WithDefaultTag(ref)

		if _, isCanonical := ref.(reference.Canonical); isCanonical {
			return nil, errors.New("build tag cannot contain a digest")
		}

		if _, isTagged := ref.(reference.NamedTagged); !isTagged {
			ref, err = reference.WithTag(ref, reference.DefaultTag)
		}

		nameWithTag := ref.String()

		if _, exists := uniqNames[nameWithTag]; !exists {
			uniqNames[nameWithTag] = struct{}{}
			repoAndTags = append(repoAndTags, ref)
		}
	}
	return repoAndTags, nil
}
Exemple #6
0
func (cli *HyperClient) PullImage(imageName string) error {
	distributionRef, err := reference.ParseNamed(imageName)
	if err != nil {
		return err
	}
	if reference.IsNameOnly(distributionRef) {
		distributionRef = reference.WithDefaultTag(distributionRef)
		fmt.Fprintf(cli.out, "Using default tag: %s\n", reference.DefaultTag)
	}

	// Resolve the Repository name from fqn to RepositoryInfo
	repoInfo, err := registry.ParseRepositoryInfo(distributionRef)
	if err != nil {
		return err
	}

	pull := func(auth types.AuthConfig) (io.ReadCloser, string, int, error) {
		return cli.client.Pull(distributionRef.String(), auth)
	}

	body, ctype, _, err := cli.requestWithLogin(repoInfo.Index, pull, "pull")
	if err != nil {
		return err
	}

	return cli.readStreamOutput(body, ctype, cli.isTerminalOut, cli.out, cli.err)
}
Exemple #7
0
func runRemove(dockerCli *command.DockerCli, opts *rmOptions) error {
	ctx := context.Background()

	var errs cli.Errors
	for _, name := range opts.plugins {
		named, err := reference.ParseNamed(name) // FIXME: validate
		if err != nil {
			return err
		}
		if reference.IsNameOnly(named) {
			named = reference.WithDefaultTag(named)
		}
		ref, ok := named.(reference.NamedTagged)
		if !ok {
			return fmt.Errorf("invalid name: %s", named.String())
		}
		// TODO: pass names to api instead of making multiple api calls
		if err := dockerCli.Client().PluginRemove(ctx, ref.String(), types.PluginRemoveOptions{Force: opts.force}); err != nil {
			errs = append(errs, err)
			continue
		}
		fmt.Fprintln(dockerCli.Out(), name)
	}
	// Do not simplify to `return errs` because even if errs == nil, it is not a nil-error interface value.
	if errs != nil {
		return errs
	}
	return nil
}
Exemple #8
0
func runPush(dockerCli *command.DockerCli, name string) error {
	named, err := reference.ParseNamed(name) // FIXME: validate
	if err != nil {
		return err
	}
	if reference.IsNameOnly(named) {
		named = reference.WithDefaultTag(named)
	}
	ref, ok := named.(reference.NamedTagged)
	if !ok {
		return fmt.Errorf("invalid name: %s", named.String())
	}

	ctx := context.Background()

	repoInfo, err := registry.ParseRepositoryInfo(named)
	if err != nil {
		return err
	}
	authConfig := command.ResolveAuthConfig(ctx, dockerCli, repoInfo.Index)

	encodedAuth, err := command.EncodeAuthToBase64(authConfig)
	if err != nil {
		return err
	}
	return dockerCli.Client().PluginPush(ctx, ref.String(), encodedAuth)
}
Exemple #9
0
func (c *containerConfig) image() string {
	raw := c.spec().Image
	ref, err := reference.ParseNamed(raw)
	if err != nil {
		return raw
	}
	return reference.WithDefaultTag(ref).String()
}
Exemple #10
0
// removeImageRef attempts to parse and remove the given image reference from
// this daemon's store of repository tag/digest references. The given
// repositoryRef must not be an image ID but a repository name followed by an
// optional tag or digest reference. If tag or digest is omitted, the default
// tag is used. Returns the resolved image reference and an error.
func (daemon *Daemon) removeImageRef(ref reference.Named) (reference.Named, error) {
	ref = reference.WithDefaultTag(ref)
	// Ignore the boolean value returned, as far as we're concerned, this
	// is an idempotent operation and it's okay if the reference didn't
	// exist in the first place.
	_, err := daemon.referenceStore.Delete(ref)

	return ref, err
}
Exemple #11
0
func (cli *DockerCli) createContainer(config *container.Config, hostConfig *container.HostConfig, networkingConfig *networktypes.NetworkingConfig, cidfile, name string) (*types.ContainerCreateResponse, error) {
	var containerIDFile *cidFile
	if cidfile != "" {
		var err error
		if containerIDFile, err = newCIDFile(cidfile); err != nil {
			return nil, err
		}
		defer containerIDFile.Close()
	}

	_, ref, err := reference.ParseIDOrReference(config.Image)
	if err != nil {
		return nil, err
	}
	if ref != nil {
		ref = reference.WithDefaultTag(ref)
	}

	//create the container
	response, err := cli.client.ContainerCreate(context.Background(), config, hostConfig, networkingConfig, name)

	//if image not found try to pull it
	if err != nil {
		if client.IsErrImageNotFound(err) && ref != nil {
			fmt.Fprintf(cli.err, "Unable to find image '%s' locally\n", ref.String())

			// we don't want to write to stdout anything apart from container.ID
			if err = cli.pullImageCustomOut(config.Image, cli.err); err != nil {
				return nil, err
			}
			// Retry
			var retryErr error
			response, retryErr = cli.client.ContainerCreate(context.Background(), config, hostConfig, networkingConfig, name)
			if retryErr != nil {
				return nil, retryErr
			}
		} else {
			return nil, err
		}
	}

	for _, warning := range response.Warnings {
		fmt.Fprintf(cli.err, "WARNING: %s\n", warning)
	}
	if containerIDFile != nil {
		if err = containerIDFile.Write(response.ID); err != nil {
			return nil, err
		}
	}
	return &response, nil
}
Exemple #12
0
// CmdPull pulls an image or a repository from the registry.
//
// Usage: docker pull [OPTIONS] IMAGENAME[:TAG|@DIGEST]
func (cli *DockerCli) CmdPull(args ...string) error {
	cmd := Cli.Subcmd("pull", []string{"NAME[:TAG|@DIGEST]"}, Cli.DockerCommands["pull"].Description, true)
	allTags := cmd.Bool([]string{"a", "-all-tags"}, false, "Download all tagged images in the repository")
	addTrustedFlags(cmd, true)
	cmd.Require(flag.Exact, 1)

	cmd.ParseFlags(args, true)
	remote := cmd.Arg(0)

	distributionRef, err := reference.ParseNamed(remote)
	if err != nil {
		return err
	}
	if *allTags && !reference.IsNameOnly(distributionRef) {
		return errors.New("tag can't be used with --all-tags/-a")
	}

	if !*allTags && reference.IsNameOnly(distributionRef) {
		distributionRef = reference.WithDefaultTag(distributionRef)
		fmt.Fprintf(cli.out, "Using default tag: %s\n", reference.DefaultTag)
	}

	var tag string
	switch x := distributionRef.(type) {
	case reference.Canonical:
		tag = x.Digest().String()
	case reference.NamedTagged:
		tag = x.Tag()
	}

	registryRef := registry.ParseReference(tag)

	// Resolve the Repository name from fqn to RepositoryInfo
	repoInfo, err := registry.ParseRepositoryInfo(distributionRef)
	if err != nil {
		return err
	}

	ctx := context.Background()

	authConfig := cli.ResolveAuthConfig(ctx, repoInfo.Index)
	requestPrivilege := cli.RegistryAuthenticationPrivilegedFunc(repoInfo.Index, "pull")

	if IsTrusted() && !registryRef.HasDigest() {
		// Check if tag is digest
		return cli.trustedPull(ctx, repoInfo, registryRef, authConfig, requestPrivilege)
	}

<<<<<<< HEAD
	return cli.imagePullPrivileged(ctx, authConfig, distributionRef.String(), requestPrivilege, *allTags)
}
Exemple #13
0
func runPull(dockerCli *command.DockerCli, opts pullOptions) error {
	distributionRef, err := reference.ParseNamed(opts.remote)
	if err != nil {
		return err
	}
	if opts.all && !reference.IsNameOnly(distributionRef) {
		return errors.New("tag can't be used with --all-tags/-a")
	}

	if !opts.all && reference.IsNameOnly(distributionRef) {
		distributionRef = reference.WithDefaultTag(distributionRef)
		fmt.Fprintf(dockerCli.Out(), "Using default tag: %s\n", reference.DefaultTag)
	}

	var tag string
	switch x := distributionRef.(type) {
	case reference.Canonical:
		tag = x.Digest().String()
	case reference.NamedTagged:
		tag = x.Tag()
	}

	registryRef := registry.ParseReference(tag)

	// Resolve the Repository name from fqn to RepositoryInfo
	repoInfo, err := registry.ParseRepositoryInfo(distributionRef)
	if err != nil {
		return err
	}

	ctx := context.Background()

	authConfig := dockerCli.ResolveAuthConfig(ctx, repoInfo.Index)
	requestPrivilege := dockerCli.RegistryAuthenticationPrivilegedFunc(repoInfo.Index, "pull")

	if command.IsTrusted() && !registryRef.HasDigest() {
		// Check if tag is digest
		err = trustedPull(ctx, dockerCli, repoInfo, registryRef, authConfig, requestPrivilege)
	} else {
		err = imagePullPrivileged(ctx, dockerCli, authConfig, distributionRef.String(), requestPrivilege, opts.all)
	}
	if err != nil {
		if strings.Contains(err.Error(), "target is a plugin") {
			return errors.New(err.Error() + " - Use `docker plugin install`")
		}
		return err
	}

	return nil
}
Exemple #14
0
func getPluginName(name string) (string, error) {
	named, err := reference.ParseNamed(name) // FIXME: validate
	if err != nil {
		return "", err
	}
	if reference.IsNameOnly(named) {
		named = reference.WithDefaultTag(named)
	}
	ref, ok := named.(reference.NamedTagged)
	if !ok {
		return "", fmt.Errorf("invalid name: %s", named.String())
	}
	return ref.String(), nil
}
Exemple #15
0
func runSet(dockerCli *client.DockerCli, name string, args []string) error {
	named, err := reference.ParseNamed(name) // FIXME: validate
	if err != nil {
		return err
	}
	if reference.IsNameOnly(named) {
		named = reference.WithDefaultTag(named)
	}
	ref, ok := named.(reference.NamedTagged)
	if !ok {
		return fmt.Errorf("invalid name: %s", named.String())
	}
	return dockerCli.Client().PluginSet(context.Background(), ref.String(), args)
}
Exemple #16
0
// parseImageName converts a string into a reference and tag value.
func parseImageName(img string) (reference.Named, string, error) {
	ref, err := reference.ParseNamed(img)
	if err != nil {
		return nil, "", err
	}
	ref = reference.WithDefaultTag(ref)
	var tag string
	switch x := ref.(type) {
	case reference.Canonical:
		tag = x.Digest().String()
	case reference.NamedTagged:
		tag = x.Tag()
	}
	return ref, tag, nil
}
Exemple #17
0
// Get returns an enabled plugin matching the given name and capability.
func (ps *Store) Get(name, capability string, mode int) (plugingetter.CompatPlugin, error) {
	var (
		p   *v2.Plugin
		err error
	)

	// Lookup using new model.
	if ps != nil {
		fullName := name
		if named, err := reference.ParseNamed(fullName); err == nil { // FIXME: validate
			if reference.IsNameOnly(named) {
				named = reference.WithDefaultTag(named)
			}
			ref, ok := named.(reference.NamedTagged)
			if !ok {
				return nil, fmt.Errorf("invalid name: %s", named.String())
			}
			fullName = ref.String()
		}
		p, err = ps.GetByName(fullName)
		if err == nil {
			p.Lock()
			p.RefCount += mode
			p.Unlock()
			if p.IsEnabled() {
				return p.FilterByCap(capability)
			}
			// Plugin was found but it is disabled, so we should not fall back to legacy plugins
			// but we should error out right away
			return nil, ErrNotFound(fullName)
		}
		if _, ok := err.(ErrNotFound); !ok {
			return nil, err
		}
	}

	// Lookup using legacy model.
	if allowV1PluginsFallback {
		p, err := plugins.Get(name, capability)
		if err != nil {
			return nil, fmt.Errorf("legacy plugin: %v", err)
		}
		return p, nil
	}

	return nil, err
}
Exemple #18
0
// Pull pulls a plugin, check if the correct privileges are provided and install the plugin.
func (pm *Manager) Pull(ctx context.Context, ref reference.Named, name string, metaHeader http.Header, authConfig *types.AuthConfig, privileges types.PluginPrivileges, outStream io.Writer) (err error) {
	pm.muGC.RLock()
	defer pm.muGC.RUnlock()

	// revalidate because Pull is public
	nameref, err := reference.ParseNamed(name)
	if err != nil {
		return errors.Wrapf(err, "failed to parse %q", name)
	}
	name = reference.WithDefaultTag(nameref).String()

	if err := pm.config.Store.validateName(name); err != nil {
		return err
	}

	tmpRootFSDir, err := ioutil.TempDir(pm.tmpDir(), ".rootfs")
	defer os.RemoveAll(tmpRootFSDir)

	dm := &downloadManager{
		tmpDir:    tmpRootFSDir,
		blobStore: pm.blobStore,
	}

	pluginPullConfig := &distribution.ImagePullConfig{
		Config: distribution.Config{
			MetaHeaders:      metaHeader,
			AuthConfig:       authConfig,
			RegistryService:  pm.config.RegistryService,
			ImageEventLogger: pm.config.LogPluginEvent,
			ImageStore:       dm,
		},
		DownloadManager: dm, // todo: reevaluate if possible to substitute distribution/xfer dependencies instead
		Schema2Types:    distribution.PluginTypes,
	}

	err = pm.pull(ctx, ref, pluginPullConfig, outStream)
	if err != nil {
		go pm.GC()
		return err
	}

	if _, err := pm.createPlugin(name, dm.configDigest, dm.blobs, tmpRootFSDir, &privileges); err != nil {
		return err
	}

	return nil
}
Exemple #19
0
// requirementsForImage selects the appropriate requirements for image.
func (pc *PolicyContext) requirementsForImage(image types.Image) (PolicyRequirements, error) {
	imageIdentity := image.IntendedDockerReference()
	// We don't technically need to parse it first in order to match the full name:tag,
	// but do so anyway to ensure that the intended identity really does follow that
	// format, or at least that it is not demonstrably wrong.
	ref, err := reference.ParseNamed(imageIdentity)
	if err != nil {
		return nil, err
	}
	ref = reference.WithDefaultTag(ref)

	// Look for a full match.
	fullyExpanded, err := fullyExpandedDockerReference(ref)
	if err != nil { // Coverage: This cannot currently happen.
		return nil, err
	}
	if req, ok := pc.Policy.Specific[fullyExpanded]; ok {
		logrus.Debugf(" Using specific policy section %s", fullyExpanded)
		return req, nil
	}

	// Look for a match of the repository, and then of the possible parent
	// namespaces. Note that this only happens on the expanded host names
	// and repository names, i.e. "busybox" is looked up as "docker.io/library/busybox",
	// then in its parent "docker.io/library"; in none of "busybox",
	// un-namespaced "library" nor in "" implicitly representing "library/".
	//
	// ref.FullName() == ref.Hostname() + "/" + ref.RemoteName(), so the last
	// iteration matches the host name (for any namespace).
	name := ref.FullName()
	for {
		if req, ok := pc.Policy.Specific[name]; ok {
			logrus.Debugf(" Using specific policy section %s", name)
			return req, nil
		}

		lastSlash := strings.LastIndex(name, "/")
		if lastSlash == -1 {
			break
		}
		name = name[:lastSlash]
	}

	logrus.Debugf(" Using default policy section")
	return pc.Policy.Default, nil
}
Exemple #20
0
// LookupWithCapability returns a plugin matching the given name and capability.
func LookupWithCapability(name, capability string) (Plugin, error) {
	var (
		p   *plugin
		err error
	)
	handleLegacy := true
	if manager != nil {
		fullName := name
		if named, err := reference.ParseNamed(fullName); err == nil { // FIXME: validate
			if reference.IsNameOnly(named) {
				named = reference.WithDefaultTag(named)
			}
			ref, ok := named.(reference.NamedTagged)
			if !ok {
				return nil, fmt.Errorf("invalid name: %s", named.String())
			}
			fullName = ref.String()
		}
		p, err = manager.get(fullName)
		if err != nil {
			if _, ok := err.(ErrNotFound); !ok {
				return nil, err
			}
			handleLegacy = manager.handleLegacy
		} else {
			handleLegacy = false
		}
	}
	if handleLegacy {
		p, err := plugins.Get(name, capability)
		if err != nil {
			return nil, fmt.Errorf("legacy plugin: %v", err)
		}
		return p, nil
	} else if err != nil {
		return nil, err
	}

	capability = strings.ToLower(capability)
	for _, typ := range p.PluginObj.Manifest.Interface.Types {
		if typ.Capability == capability && typ.Prefix == "docker" {
			return p, nil
		}
	}
	return nil, ErrInadequateCapability{name, capability}
}
Exemple #21
0
func runDisable(dockerCli *command.DockerCli, name string) error {
	named, err := reference.ParseNamed(name) // FIXME: validate
	if err != nil {
		return err
	}
	if reference.IsNameOnly(named) {
		named = reference.WithDefaultTag(named)
	}
	ref, ok := named.(reference.NamedTagged)
	if !ok {
		return fmt.Errorf("invalid name: %s", named.String())
	}
	if err := dockerCli.Client().PluginDisable(context.Background(), ref.String()); err != nil {
		return err
	}
	fmt.Fprintln(dockerCli.Out(), name)
	return nil
}
Exemple #22
0
// Get returns the imageID for a parsed reference
func (store *repoCache) Get(ref reference.Named) (string, error) {
	defer trace.End(trace.Begin(""))
	ref = reference.WithDefaultTag(ref)

	store.mu.RLock()
	defer store.mu.RUnlock()

	repository, exists := store.Repositories[ref.Name()]
	if !exists || repository == nil {
		return "", ErrDoesNotExist
	}
	imageID, exists := repository[ref.String()]
	if !exists {
		return "", ErrDoesNotExist
	}

	return imageID, nil
}
Exemple #23
0
func runInstall(dockerCli *command.DockerCli, opts pluginOptions) error {
	named, err := reference.ParseNamed(opts.name) // FIXME: validate
	if err != nil {
		return err
	}
	if reference.IsNameOnly(named) {
		named = reference.WithDefaultTag(named)
	}
	ref, ok := named.(reference.NamedTagged)
	if !ok {
		return fmt.Errorf("invalid name: %s", named.String())
	}

	ctx := context.Background()

	repoInfo, err := registry.ParseRepositoryInfo(named)
	if err != nil {
		return err
	}

	authConfig := command.ResolveAuthConfig(ctx, dockerCli, repoInfo.Index)

	encodedAuth, err := command.EncodeAuthToBase64(authConfig)
	if err != nil {
		return err
	}

	registryAuthFunc := command.RegistryAuthenticationPrivilegedFunc(dockerCli, repoInfo.Index, "plugin install")

	options := types.PluginInstallOptions{
		RegistryAuth:          encodedAuth,
		Disabled:              opts.disable,
		AcceptAllPermissions:  opts.grantPerms,
		AcceptPermissionsFunc: acceptPrivileges(dockerCli, opts.name),
		// TODO: Rename PrivilegeFunc, it has nothing to do with privileges
		PrivilegeFunc: registryAuthFunc,
		Args:          opts.args,
	}
	if err := dockerCli.Client().PluginInstall(ctx, ref.String(), options); err != nil {
		return err
	}
	fmt.Fprintln(dockerCli.Out(), opts.name)
	return nil
}
Exemple #24
0
// Delete deletes a reference from the store. It returns true if a deletion
// happened, or false otherwise.
func (store *repoCache) Delete(ref reference.Named, save bool) (bool, error) {
	defer trace.End(trace.Begin(""))
	ref = reference.WithDefaultTag(ref)

	store.mu.Lock()
	defer store.mu.Unlock()
	var err error
	// return code -- assume success
	rtc := true
	repoName := ref.Name()

	repository, exists := store.Repositories[repoName]
	if !exists {
		return false, ErrDoesNotExist
	}
	refStr := ref.String()
	if imageID, exists := repository[refStr]; exists {
		delete(repository, refStr)
		if len(repository) == 0 {
			delete(store.Repositories, repoName)
		}
		if store.referencesByIDCache[imageID] != nil {
			delete(store.referencesByIDCache[imageID], refStr)
			if len(store.referencesByIDCache[imageID]) == 0 {
				delete(store.referencesByIDCache, imageID)
			}
		}
		if layer, exists := store.images[imageID]; exists {
			delete(store.Layers, imageID)
			delete(store.images, layer)
		}
		if save {
			err = store.Save()
			if err != nil {
				rtc = false
			}
		}
		return rtc, err
	}

	return false, ErrDoesNotExist
}
Exemple #25
0
func (cli *HyperClient) PullImage(imageName string) error {
	distributionRef, err := reference.ParseNamed(imageName)
	if err != nil {
		return err
	}
	if reference.IsNameOnly(distributionRef) {
		distributionRef = reference.WithDefaultTag(distributionRef)
		fmt.Fprintf(cli.out, "Using default tag: %s\n", reference.DefaultTag)
	}

	// Resolve the Repository name from fqn to RepositoryInfo
	repoInfo, err := registry.ParseRepositoryInfo(distributionRef)
	if err != nil {
		return err
	}

	v := url.Values{}
	v.Set("imageName", distributionRef.String())
	_, _, err = cli.clientRequestAttemptLogin("POST", "/image/create?"+v.Encode(), nil, cli.out, repoInfo.Index, "pull")
	return err
}
Exemple #26
0
func runInspect(dockerCli *client.DockerCli, opts inspectOptions) error {
	client := dockerCli.Client()
	ctx := context.Background()
	getRef := func(name string) (interface{}, []byte, error) {
		named, err := reference.ParseNamed(name) // FIXME: validate
		if err != nil {
			return nil, nil, err
		}
		if reference.IsNameOnly(named) {
			named = reference.WithDefaultTag(named)
		}
		ref, ok := named.(reference.NamedTagged)
		if !ok {
			return nil, nil, fmt.Errorf("invalid name: %s", named.String())
		}

		return client.PluginInspectWithRaw(ctx, ref.String())
	}

	return inspect.Inspect(dockerCli.Out(), opts.pluginNames, opts.format, getRef)
}
Exemple #27
0
func resolveServiceImageDigest(dockerCli *command.DockerCli, service *swarm.ServiceSpec) error {
	if !command.IsTrusted() {
		// Digests are resolved by the daemon when not using content
		// trust.
		return nil
	}

	image := service.TaskTemplate.ContainerSpec.Image

	// We only attempt to resolve the digest if the reference
	// could be parsed as a digest reference. Specifying an image ID
	// is valid but not resolvable. There is no warning message for
	// an image ID because it's valid to use one.
	if _, err := digest.ParseDigest(image); err == nil {
		return nil
	}

	ref, err := reference.ParseNamed(image)
	if err != nil {
		return fmt.Errorf("Could not parse image reference %s", service.TaskTemplate.ContainerSpec.Image)
	}
	if _, ok := ref.(reference.Canonical); !ok {
		ref = reference.WithDefaultTag(ref)

		taggedRef, ok := ref.(reference.NamedTagged)
		if !ok {
			// This should never happen because a reference either
			// has a digest, or WithDefaultTag would give it a tag.
			return errors.New("Failed to resolve image digest using content trust: reference is missing a tag")
		}

		resolvedImage, err := trustedResolveDigest(context.Background(), dockerCli, taggedRef)
		if err != nil {
			return fmt.Errorf("Failed to resolve image digest using content trust: %v", err)
		}
		logrus.Debugf("resolved image tag to %s using content trust", resolvedImage.String())
		service.TaskTemplate.ContainerSpec.Image = resolvedImage.String()
	}
	return nil
}
Exemple #28
0
func (cli *DockerCli) pullImageCustomOut(image string, out io.Writer) error {
	ref, err := reference.ParseNamed(image)
	if err != nil {
		return err
	}

	var tag string
	switch x := reference.WithDefaultTag(ref).(type) {
	case reference.Canonical:
		tag = x.Digest().String()
	case reference.NamedTagged:
		tag = x.Tag()
	}

	// Resolve the Repository name from fqn to RepositoryInfo
	repoInfo, err := registry.ParseRepositoryInfo(ref)
	if err != nil {
		return err
	}

	authConfig := cli.resolveAuthConfig(cli.configFile.AuthConfigs, repoInfo.Index)
	encodedAuth, err := encodeAuthToBase64(authConfig)
	if err != nil {
		return err
	}

	options := types.ImageCreateOptions{
		Parent:       ref.Name(),
		Tag:          tag,
		RegistryAuth: encodedAuth,
	}

	responseBody, err := cli.client.ImageCreate(options)
	if err != nil {
		return err
	}
	defer responseBody.Close()

	return jsonmessage.DisplayJSONMessagesStream(responseBody, out, cli.outFd, cli.isTerminalOut, nil)
}
Exemple #29
0
// imageWithDigestString takes an image such as name or name:tag
// and returns the image pinned to a digest, such as name@sha256:34234...
// Due to the difference between the docker/docker/reference, and the
// docker/distribution/reference packages, we're parsing the image twice.
// As the two packages converge, this function should be simplified.
// TODO(nishanttotla): After the packages converge, the function must
// convert distreference.Named -> distreference.Canonical, and the logic simplified.
func (c *Cluster) imageWithDigestString(ctx context.Context, image string, authConfig *apitypes.AuthConfig) (string, error) {
	if _, err := digest.ParseDigest(image); err == nil {
		return "", errors.New("image reference is an image ID")
	}
	ref, err := distreference.ParseNamed(image)
	if err != nil {
		return "", err
	}
	// only query registry if not a canonical reference (i.e. with digest)
	if _, ok := ref.(distreference.Canonical); !ok {
		// create a docker/docker/reference Named object because GetRepository needs it
		dockerRef, err := reference.ParseNamed(image)
		if err != nil {
			return "", err
		}
		dockerRef = reference.WithDefaultTag(dockerRef)
		namedTaggedRef, ok := dockerRef.(reference.NamedTagged)
		if !ok {
			return "", errors.New("unable to cast image to NamedTagged reference object")
		}

		repo, _, err := c.config.Backend.GetRepository(ctx, namedTaggedRef, authConfig)
		if err != nil {
			return "", err
		}
		dscrptr, err := repo.Tags(ctx).Get(ctx, namedTaggedRef.Tag())
		if err != nil {
			return "", err
		}

		namedDigestedRef, err := distreference.WithDigest(distreference.EnsureTagged(ref), dscrptr.Digest)
		if err != nil {
			return "", err
		}
		return namedDigestedRef.String(), nil
	}
	// reference already contains a digest, so just return it
	return ref.String(), nil
}
Exemple #30
0
func (ps *Store) resolvePluginID(idOrName string) (string, error) {
	ps.RLock() // todo: fix
	defer ps.RUnlock()

	if validFullID.MatchString(idOrName) {
		return idOrName, nil
	}

	ref, err := reference.ParseNamed(idOrName)
	if err != nil {
		return "", errors.WithStack(ErrNotFound(idOrName))
	}
	if _, ok := ref.(reference.Canonical); ok {
		logrus.Warnf("canonical references cannot be resolved: %v", ref.String())
		return "", errors.WithStack(ErrNotFound(idOrName))
	}

	fullRef := reference.WithDefaultTag(ref)

	for _, p := range ps.plugins {
		if p.PluginObj.Name == fullRef.String() {
			return p.PluginObj.ID, nil
		}
	}

	var found *v2.Plugin
	for id, p := range ps.plugins { // this can be optimized
		if strings.HasPrefix(id, idOrName) {
			if found != nil {
				return "", errors.WithStack(ErrAmbiguous(idOrName))
			}
			found = p
		}
	}
	if found == nil {
		return "", errors.WithStack(ErrNotFound(idOrName))
	}
	return found.PluginObj.ID, nil
}