// parseDockerReferences converts two reference strings into parsed entities, failing on any error func parseDockerReferences(s1, s2 string) (reference.Named, reference.Named, error) { r1, err := reference.ParseNamed(s1) if err != nil { return nil, nil, err } r2, err := reference.ParseNamed(s2) if err != nil { return nil, nil, err } return r1, r2, nil }
// 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) }
// 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 pullImage(ctx context.Context, dockerCli *command.DockerCli, image string, out io.Writer) error { ref, err := reference.ParseNamed(image) if err != nil { return err } // Resolve the Repository name from fqn to RepositoryInfo repoInfo, err := registry.ParseRepositoryInfo(ref) if err != nil { return err } authConfig := dockerCli.ResolveAuthConfig(ctx, repoInfo.Index) encodedAuth, err := command.EncodeAuthToBase64(authConfig) if err != nil { return err } options := types.ImageCreateOptions{ RegistryAuth: encodedAuth, } responseBody, err := dockerCli.Client().ImageCreate(ctx, image, options) if err != nil { return err } defer responseBody.Close() return jsonmessage.DisplayJSONMessagesStream( responseBody, out, dockerCli.Out().FD(), dockerCli.Out().IsTerminal(), nil) }
func (cli *DockerCli) pullImage(image string, out io.Writer) error { ref, err := reference.ParseNamed(image) if err != nil { return err } // Resolve the Repository name from fqn to RepositoryInfo repoInfo, err := registry.ParseRepositoryInfo(ref) if err != nil { return err } authConfig := cli.resolveAuthConfig(repoInfo.Index) encodedAuth, err := encodeAuthToBase64(authConfig) if err != nil { return err } options := types.ImageCreateOptions{ RegistryAuth: encodedAuth, } responseBody, err := cli.client.ImageCreate(context.Background(), image, options) if err != nil { return err } defer responseBody.Close() return jsonmessage.DisplayJSONMessagesStream(responseBody, out, cli.outFd, cli.isTerminalOut, nil) }
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) }
// CmdPush pushes an image or repository to the registry. // // Usage: docker push NAME[:TAG] func (cli *DockerCli) CmdPush(args ...string) error { cmd := Cli.Subcmd("push", []string{"NAME[:TAG]"}, Cli.DockerCommands["push"].Description, true) addTrustedFlags(cmd, false) cmd.Require(flag.Exact, 1) cmd.ParseFlags(args, true) ref, err := reference.ParseNamed(cmd.Arg(0)) if err != nil { return err } // Resolve the Repository name from fqn to RepositoryInfo repoInfo, err := registry.ParseRepositoryInfo(ref) if err != nil { return err } // Resolve the Auth config relevant for this server authConfig := cli.resolveAuthConfig(repoInfo.Index) requestPrivilege := cli.registryAuthenticationPrivilegedFunc(repoInfo.Index, "push") if isTrusted() { return cli.trustedPush(repoInfo, ref, authConfig, requestPrivilege) } responseBody, err := cli.imagePushPrivileged(authConfig, ref.String(), requestPrivilege) if err != nil { return err } defer responseBody.Close() return jsonmessage.DisplayJSONMessagesStream(responseBody, cli.out, cli.outFd, cli.isTerminalOut, nil) }
// getRepositoryMountCandidates returns an array of v2 metadata items belonging to the given registry. The // array is sorted from youngest to oldest. If requireReigstryMatch is true, the resulting array will contain // only metadata entries having registry part of SourceRepository matching the part of repoInfo. func getRepositoryMountCandidates( repoInfo reference.Named, hmacKey []byte, max int, v2Metadata []metadata.V2Metadata, ) []metadata.V2Metadata { candidates := []metadata.V2Metadata{} for _, meta := range v2Metadata { sourceRepo, err := reference.ParseNamed(meta.SourceRepository) if err != nil || repoInfo.Hostname() != sourceRepo.Hostname() { continue } // target repository is not a viable candidate if meta.SourceRepository == repoInfo.FullName() { continue } candidates = append(candidates, meta) } sortV2MetadataByLikenessAndAge(repoInfo, hmacKey, candidates) if max >= 0 && len(candidates) > max { // select the youngest metadata candidates = candidates[:max] } return candidates }
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) }
func AddMockImageToCache() { mockImage := &metadata.ImageConfig{ ImageID: "e732471cb81a564575aad46b9510161c5945deaf18e9be3db344333d72f0b4b2", Name: "busybox", Tags: []string{"latest"}, Reference: "busybox:latest", } mockImage.Config = &container.Config{ Hostname: "55cd1f8f6e5b", Domainname: "", User: "", AttachStdin: false, AttachStdout: false, AttachStderr: false, Tty: false, OpenStdin: false, StdinOnce: false, Env: []string{"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"}, Cmd: []string{"sh"}, Image: "sha256:e732471cb81a564575aad46b9510161c5945deaf18e9be3db344333d72f0b4b2", Volumes: nil, WorkingDir: "", Entrypoint: nil, OnBuild: nil, } cache.ImageCache().Add(mockImage) ref, _ := reference.ParseNamed(mockImage.Reference) cache.RepositoryCache().AddReference(ref, mockImage.ImageID, false, mockImage.ImageID, false) }
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) }
// ReferencesByName returns the references for a given repository name. // If there are no references known for this repository name, // ReferencesByName returns nil. func (store *repoCache) ReferencesByName(ref reference.Named) []Association { defer trace.End(trace.Begin("")) store.mu.RLock() defer store.mu.RUnlock() repository, exists := store.Repositories[ref.Name()] if !exists { return nil } var associations []Association for refStr, refID := range repository { ref, err := reference.ParseNamed(refStr) if err != nil { // Should never happen return nil } associations = append(associations, Association{ Ref: ref, ImageID: refID, }) } sort.Sort(lexicalAssociations(associations)) return associations }
// NewRespositoryCache will create a new repoCache or rehydrate // an existing repoCache from the portlayer k/v store func NewRepositoryCache(client *client.PortLayer) error { defer trace.End(trace.Begin("")) rCache.client = client val, err := kv.Get(client, repoKey) if err != nil && err != kv.ErrKeyNotFound { return err } if val != "" { if err = json.Unmarshal([]byte(val), rCache); err != nil { return fmt.Errorf("Failed to unmarshal repository cache: %s", err) } // hydrate refByIDCache for _, repository := range rCache.Repositories { for refStr, refID := range repository { ref, _ := reference.ParseNamed(refStr) if rCache.referencesByIDCache[refID] == nil { rCache.referencesByIDCache[refID] = make(map[string]reference.Named) } rCache.referencesByIDCache[refID][refStr] = ref } } // hydrate image -> layer cache for image, layer := range rCache.Layers { rCache.images[image] = layer } log.Infof("found %d repositories", len(rCache.Repositories)) log.Infof("found %d image layers", len(rCache.Layers)) } return nil }
// CmdPush pushes an image or repository to the registry. // // Usage: hyperctl push NAME[:TAG] func (cli *HyperClient) HyperCmdPush(args ...string) error { var parser = gflag.NewParser(nil, gflag.Default) parser.Usage = "push NAME[:TAG]\n\nPush an image to a Docker registry server" args, err := parser.ParseArgs(args) if err != nil { if !strings.Contains(err.Error(), "Usage") { return err } else { return nil } } // we need to get the image name which will be used to create a container if len(args) == 0 { return fmt.Errorf("\"push\" requires a minimum of 1 argument, please provide the image name.") } name := args[0] ref, err := reference.ParseNamed(name) if err != nil { return err } var tag string switch x := ref.(type) { case reference.Canonical: return fmt.Errorf("cannot push a digest reference") case reference.NamedTagged: tag = x.Tag() } // Resolve the Repository name from fqn to RepositoryInfo repoInfo, err := registry.ParseRepositoryInfo(ref) if err != nil { return err } // Resolve the Auth config relevant for this server authConfig := registry.ResolveAuthConfig(cli.configFile.AuthConfigs, repoInfo.Index) // If we're not using a custom registry, we know the restrictions // applied to repository names and can warn the user in advance. // Custom repositories can have different rules, and we must also // allow pushing by image ID. if repoInfo.Official { username := authConfig.Username if username == "" { username = "******" } return fmt.Errorf("You cannot push a \"root\" repository. Please rename your repository to <user>/<repo> (ex: %s/%s)", username, ref.Name()) } push := func(auth types.AuthConfig) (io.ReadCloser, string, int, error) { return cli.client.Push(tag, repoInfo.String(), auth) } body, ctype, _, err := cli.requestWithLogin(repoInfo.Index, push, "push") if err != nil { return err } return cli.readStreamOutput(body, ctype, cli.isTerminalOut, cli.out, cli.err) }
// CmdPush pushes an image or repository to the registry. // // Usage: docker push NAME[:TAG] func (cli *DockerCli) CmdPush(args ...string) error { cmd := Cli.Subcmd("push", []string{"NAME[:TAG]"}, Cli.DockerCommands["push"].Description, true) addTrustedFlags(cmd, false) cmd.Require(flag.Exact, 1) cmd.ParseFlags(args, true) ref, err := reference.ParseNamed(cmd.Arg(0)) if err != nil { return err } var tag string switch x := ref.(type) { case reference.Canonical: return errors.New("cannot push a digest reference") case reference.NamedTagged: tag = x.Tag() } // Resolve the Repository name from fqn to RepositoryInfo repoInfo, err := registry.ParseRepositoryInfo(ref) if err != nil { return err } // Resolve the Auth config relevant for this server authConfig := registry.ResolveAuthConfig(cli.configFile.AuthConfigs, repoInfo.Index) requestPrivilege := cli.registryAuthenticationPrivilegedFunc(repoInfo.Index, "push") if isTrusted() { return cli.trustedPush(repoInfo, tag, authConfig, requestPrivilege) } return cli.imagePushPrivileged(authConfig, ref.Name(), tag, cli.out, requestPrivilege) }
// CmdTag tags an image into a repository. // // Usage: docker tag [OPTIONS] IMAGE[:TAG] [REGISTRYHOST/][USERNAME/]NAME[:TAG] func (cli *DockerCli) CmdTag(args ...string) error { cmd := Cli.Subcmd("tag", []string{"IMAGE[:TAG] [REGISTRYHOST/][USERNAME/]NAME[:TAG]"}, Cli.DockerCommands["tag"].Description, true) force := cmd.Bool([]string{"#f", "#-force"}, false, "Force the tagging even if there's a conflict") cmd.Require(flag.Exact, 2) cmd.ParseFlags(args, true) ref, err := reference.ParseNamed(cmd.Arg(1)) if err != nil { return err } if _, isCanonical := ref.(reference.Canonical); isCanonical { return errors.New("refusing to create a tag with a digest reference") } var tag string if tagged, isTagged := ref.(reference.NamedTagged); isTagged { tag = tagged.Tag() } options := types.ImageTagOptions{ ImageID: cmd.Arg(0), RepositoryName: ref.Name(), Tag: tag, Force: *force, } return cli.client.ImageTag(context.Background(), options) }
// GetRef returns the distribution reference for a given name. func GetRef(name string) (reference.Named, error) { ref, err := reference.ParseNamed(name) if err != nil { return nil, err } return ref, nil }
// updateRepositoryCache will update the repository cache // that resides in the docker persona. This will add image tag, // digest and layer information. func updateRepositoryCache(ic *ImageC) error { // LayerID for the image layer imageLayerID := ic.ImageLayers[0].ID ref, err := reference.ParseNamed(ic.Reference) if err != nil { return fmt.Errorf("Unable to parse reference: %s", err.Error()) } // get the repoCache repoCache := cache.RepositoryCache() // In the case that we don't have the ImageID, then we need // to go to the RepositoryCache to get it. if ic.ImageID == "" { // call to repository cache for the imageID for this layer ic.ImageID = repoCache.GetImageID(imageLayerID) // if we still don't have an imageID we can't continue if ic.ImageID == "" { return fmt.Errorf("ImageID not found by LayerID(%s) in RepositoryCache", imageLayerID) } } // AddReference will add the tag / digest as appropriate and will persist // to the portlayer k/v err = repoCache.AddReference(ref, ic.ImageID, false, imageLayerID, true) if err != nil { return fmt.Errorf("Unable to Add Image Reference(%s): %s", ref.String(), err.Error()) } return nil }
// 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 }
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 }
// 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) }
// GetImageID returns an image ID corresponding to the image referred to by // refOrID. func (daemon *Daemon) GetImageID(refOrID string) (image.ID, error) { // Treat as an ID if id, err := digest.ParseDigest(refOrID); err == nil { if _, err := daemon.imageStore.Get(image.ID(id)); err != nil { return "", ErrImageDoesNotExist{refOrID} } return image.ID(id), nil } // Treat it as a possible tag or digest reference if ref, err := reference.ParseNamed(refOrID); err == nil { if id, err := daemon.referenceStore.Get(ref); err == nil { return id, nil } if tagged, ok := ref.(reference.NamedTagged); ok { if id, err := daemon.imageStore.Search(tagged.Tag()); err == nil { for _, namedRef := range daemon.referenceStore.References(id) { if namedRef.Name() == ref.Name() { return id, nil } } } } } // Search based on ID if id, err := daemon.imageStore.Search(refOrID); err == nil { return id, nil } return "", ErrImageDoesNotExist{refOrID} }
func runPush(dockerCli *command.DockerCli, remote string) error { ref, err := reference.ParseNamed(remote) if err != nil { return err } // Resolve the Repository name from fqn to RepositoryInfo repoInfo, err := registry.ParseRepositoryInfo(ref) if err != nil { return err } ctx := context.Background() // Resolve the Auth config relevant for this server authConfig := command.ResolveAuthConfig(ctx, dockerCli, repoInfo.Index) requestPrivilege := command.RegistryAuthenticationPrivilegedFunc(dockerCli, repoInfo.Index, "push") if command.IsTrusted() { return trustedPush(ctx, dockerCli, repoInfo, ref, authConfig, requestPrivilege) } responseBody, err := imagePushPrivileged(ctx, dockerCli, authConfig, ref.String(), requestPrivilege) if err != nil { return err } defer responseBody.Close() return jsonmessage.DisplayJSONMessagesToStream(responseBody, dockerCli.Out(), nil) }
// PullImage initiates a pull operation. image is the repository name to pull, and // tag may be either empty, or indicate a specific tag to pull. func (daemon *Daemon) PullImage(ctx context.Context, image, tag string, metaHeaders map[string][]string, authConfig *types.AuthConfig, outStream io.Writer) error { // Special case: "pull -a" may send an image name with a // trailing :. This is ugly, but let's not break API // compatibility. image = strings.TrimSuffix(image, ":") ref, err := reference.ParseNamed(image) if err != nil { return err } if tag != "" { // The "tag" could actually be a digest. var dgst digest.Digest dgst, err = digest.ParseDigest(tag) if err == nil { ref, err = reference.WithDigest(ref, dgst) } else { ref, err = reference.WithTag(ref, tag) } if err != nil { return err } } return daemon.pullImageWithReference(ctx, ref, metaHeaders, authConfig, outStream) }
func TestPushImageJSONIndex(t *testing.T) { r := spawnTestRegistrySession(t) imgData := []*ImgData{ { ID: "77dbf71da1d00e3fbddc480176eac8994025630c6590d11cfc8fe1209c2a1d20", Checksum: "sha256:1ac330d56e05eef6d438586545ceff7550d3bdcb6b19961f12c5ba714ee1bb37", }, { ID: "42d718c941f5c532ac049bf0b0ab53f0062f09a03afd4aa4a02c098e46032b9d", Checksum: "sha256:bea7bf2e4bacd479344b737328db47b18880d09096e6674165533aa994f5e9f2", }, } repoRef, err := reference.ParseNamed(REPO) if err != nil { t.Fatal(err) } repoData, err := r.PushImageJSONIndex(repoRef, imgData, false, nil) if err != nil { t.Fatal(err) } if repoData == nil { t.Fatal("Expected RepositoryData object") } repoData, err = r.PushImageJSONIndex(repoRef, imgData, true, []string{r.indexEndpoint.String()}) if err != nil { t.Fatal(err) } if repoData == nil { t.Fatal("Expected RepositoryData object") } }
func stripTag(image string) string { ref, err := reference.ParseNamed(image) if err != nil { return image } return ref.Name() }
// CmdImport creates an empty filesystem image, imports the contents of the tarball into the image, and optionally tags the image. // // The URL argument is the address of a tarball (.tar, .tar.gz, .tgz, .bzip, .tar.xz, .txz) file or a path to local file relative to docker client. If the URL is '-', then the tar file is read from STDIN. // // Usage: docker import [OPTIONS] file|URL|- [REPOSITORY[:TAG]] func (cli *DockerCli) CmdImport(args ...string) error { cmd := Cli.Subcmd("import", []string{"file|URL|- [REPOSITORY[:TAG]]"}, Cli.DockerCommands["import"].Description, true) flChanges := opts.NewListOpts(nil) cmd.Var(&flChanges, []string{"c", "-change"}, "Apply Dockerfile instruction to the created image") message := cmd.String([]string{"m", "-message"}, "", "Set commit message for imported image") cmd.Require(flag.Min, 1) cmd.ParseFlags(args, true) var ( in io.Reader tag string src = cmd.Arg(0) srcName = src repository = cmd.Arg(1) changes = flChanges.GetAll() ) if cmd.NArg() == 3 { fmt.Fprintf(cli.err, "[DEPRECATED] The format 'file|URL|- [REPOSITORY [TAG]]' has been deprecated. Please use file|URL|- [REPOSITORY[:TAG]]\n") tag = cmd.Arg(2) } if repository != "" { //Check if the given image name can be resolved if _, err := reference.ParseNamed(repository); err != nil { return err } } if src == "-" { in = cli.in } else if !urlutil.IsURL(src) { srcName = "-" file, err := os.Open(src) if err != nil { return err } defer file.Close() in = file } options := types.ImageImportOptions{ Source: in, SourceName: srcName, RepositoryName: repository, Message: *message, Tag: tag, Changes: changes, } responseBody, err := cli.client.ImageImport(options) if err != nil { return err } defer responseBody.Close() return jsonmessage.DisplayJSONMessagesStream(responseBody, cli.out, cli.outFd, cli.isTerminalOut) }
// validateTag checks if the given image name can be resolved. func validateTag(rawRepo string) (string, error) { _, err := reference.ParseNamed(rawRepo) if err != nil { return "", err } return rawRepo, nil }
func (c *containerConfig) image() string { raw := c.spec().Image ref, err := reference.ParseNamed(raw) if err != nil { return raw } return reference.WithDefaultTag(ref).String() }
func getPathComponents(path string) []string { // make sure to add docker.io/ prefix to the path named, err := reference.ParseNamed(path) if err == nil { path = named.FullName() } return strings.Split(path, "/") }