func createContainer(ctx context.Context, dockerCli *command.DockerCli, config *container.Config, hostConfig *container.HostConfig, networkingConfig *networktypes.NetworkingConfig, cidfile, name string) (*types.ContainerCreateResponse, error) { stderr := dockerCli.Err() var containerIDFile *cidFile if cidfile != "" { var err error if containerIDFile, err = newCIDFile(cidfile); err != nil { return nil, err } defer containerIDFile.Close() } var trustedRef reference.Canonical _, ref, err := reference.ParseIDOrReference(config.Image) if err != nil { return nil, err } if ref != nil { ref = reference.WithDefaultTag(ref) if ref, ok := ref.(reference.NamedTagged); ok && command.IsTrusted() { var err error trustedRef, err = image.TrustedReference(ctx, dockerCli, ref) if err != nil { return nil, err } config.Image = trustedRef.String() } } //create the container response, err := dockerCli.Client().ContainerCreate(ctx, config, hostConfig, networkingConfig, name) //if image not found try to pull it if err != nil { if apiclient.IsErrImageNotFound(err) && ref != nil { fmt.Fprintf(stderr, "Unable to find image '%s' locally\n", ref.String()) // we don't want to write to stdout anything apart from container.ID if err = pullImage(ctx, dockerCli, config.Image, stderr); err != nil { return nil, err } if ref, ok := ref.(reference.NamedTagged); ok && trustedRef != nil { if err := image.TagTrusted(ctx, dockerCli, trustedRef, ref); err != nil { return nil, err } } // Retry var retryErr error response, retryErr = dockerCli.Client().ContainerCreate(ctx, config, hostConfig, networkingConfig, name) if retryErr != nil { return nil, retryErr } } else { return nil, err } } for _, warning := range response.Warnings { fmt.Fprintf(stderr, "WARNING: %s\n", warning) } if containerIDFile != nil { if err = containerIDFile.Write(response.ID); err != nil { return nil, err } } return &response, nil }
func runInstall(dockerCli *command.DockerCli, opts pluginOptions) error { // Parse name using distribution reference package to support name // containing both tag and digest. Names with both tag and digest // will be treated by the daemon as a pull by digest with // an alias for the tag (if no alias is provided). ref, err := distreference.ParseNamed(opts.name) if err != nil { return err } alias := "" if opts.alias != "" { aref, err := reference.ParseNamed(opts.alias) if err != nil { return err } aref = reference.WithDefaultTag(aref) if _, ok := aref.(reference.NamedTagged); !ok { return fmt.Errorf("invalid name: %s", opts.alias) } alias = aref.String() } ctx := context.Background() index, err := getRepoIndexFromUnnormalizedRef(ref) if err != nil { return err } remote := ref.String() _, isCanonical := ref.(distreference.Canonical) if command.IsTrusted() && !isCanonical { if alias == "" { alias = ref.String() } var nt reference.NamedTagged named, err := reference.ParseNamed(ref.Name()) if err != nil { return err } if tagged, ok := ref.(distreference.Tagged); ok { nt, err = reference.WithTag(named, tagged.Tag()) if err != nil { return err } } else { named = reference.WithDefaultTag(named) nt = named.(reference.NamedTagged) } trusted, err := image.TrustedReference(ctx, dockerCli, nt, newRegistryService()) if err != nil { return err } remote = trusted.String() } authConfig := command.ResolveAuthConfig(ctx, dockerCli, index) encodedAuth, err := command.EncodeAuthToBase64(authConfig) if err != nil { return err } registryAuthFunc := command.RegistryAuthenticationPrivilegedFunc(dockerCli, index, "plugin install") options := types.PluginInstallOptions{ RegistryAuth: encodedAuth, RemoteRef: remote, 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, } responseBody, err := dockerCli.Client().PluginInstall(ctx, alias, options) if err != nil { if strings.Contains(err.Error(), "target is image") { return errors.New(err.Error() + " - Use `docker image pull`") } return err } defer responseBody.Close() if err := jsonmessage.DisplayJSONMessagesToStream(responseBody, dockerCli.Out(), nil); err != nil { return err } fmt.Fprintf(dockerCli.Out(), "Installed plugin %s\n", opts.name) // todo: return proper values from the API for this result return nil }