// RunImportImage contains all the necessary functionality for the OpenShift cli import-image command. func RunImportImage(f *clientcmd.Factory, out io.Writer, cmd *cobra.Command, args []string) error { if len(args) == 0 || len(args[0]) == 0 { return cmdutil.UsageError(cmd, "you must specify the name of an image stream.") } streamName := args[0] namespace, _, err := f.DefaultNamespace() if err != nil { return err } osClient, _, err := f.Clients() if err != nil { return err } imageStreamClient := osClient.ImageStreams(namespace) stream, err := imageStreamClient.Get(streamName) if err != nil { return err } if len(stream.Spec.DockerImageRepository) == 0 { return errors.New("only image streams with spec.dockerImageRepository set may have images imported") } if stream.Annotations == nil { stream.Annotations = make(map[string]string) } stream.Annotations[imageapi.DockerImageRepositoryCheckAnnotation] = "" updatedStream, err := imageStreamClient.Update(stream) if err != nil { return err } resourceVersion := updatedStream.ResourceVersion fmt.Fprintln(cmd.Out(), "Waiting for the import to complete, CTRL+C to stop waiting.") updatedStream, err = waitForImport(imageStreamClient, stream.Name, resourceVersion) if err != nil { return fmt.Errorf("unable to determine if the import completed successfully - please run 'oc describe -n %s imagestream/%s' to see if the tags were updated as expected: %v", stream.Namespace, stream.Name, err) } fmt.Fprintln(cmd.Out(), "The import completed successfully.\n") d := describe.ImageStreamDescriber{osClient} info, err := d.Describe(updatedStream.Namespace, updatedStream.Name) if err != nil { return err } fmt.Fprintln(out, info) return nil }
// RunImportImage contains all the necessary functionality for the OpenShift cli import-image command. func RunImportImage(f *clientcmd.Factory, out io.Writer, cmd *cobra.Command, args []string) error { if len(args) == 0 || len(args[0]) == 0 { return cmdutil.UsageError(cmd, "you must specify the name of an image stream") } streamName := args[0] namespace, _, err := f.DefaultNamespace() if err != nil { return err } osClient, _, err := f.Clients() if err != nil { return err } from := cmdutil.GetFlagString(cmd, "from") confirm := cmdutil.GetFlagBool(cmd, "confirm") imageStreamClient := osClient.ImageStreams(namespace) stream, err := imageStreamClient.Get(streamName) if err != nil { if len(from) == 0 || !errors.IsNotFound(err) { return err } if !confirm { return fmt.Errorf("the image stream does not exist, pass --confirm to create") } stream = &imageapi.ImageStream{ ObjectMeta: kapi.ObjectMeta{Name: streamName}, Spec: imageapi.ImageStreamSpec{DockerImageRepository: from}, } } else { if len(stream.Spec.DockerImageRepository) == 0 { if len(from) == 0 { return fmt.Errorf("only image streams with spec.dockerImageRepository set may have images imported") } if !confirm { return fmt.Errorf("the image stream already has an import repository set, pass --confirm to update") } stream.Spec.DockerImageRepository = from } else { if len(from) != 0 { if from != stream.Spec.DockerImageRepository { if !confirm { return fmt.Errorf("the image stream has a different import spec %q, pass --confirm to update", stream.Spec.DockerImageRepository) } } } } } if stream.Annotations != nil { delete(stream.Annotations, imageapi.DockerImageRepositoryCheckAnnotation) } if stream.CreationTimestamp.IsZero() { stream, err = imageStreamClient.Create(stream) } else { stream, err = imageStreamClient.Update(stream) } if err != nil { return err } resourceVersion := stream.ResourceVersion fmt.Fprintln(cmd.Out(), "Waiting for the import to complete, CTRL+C to stop waiting.") stream, err = waitForImport(imageStreamClient, stream.Name, resourceVersion) if err != nil { return fmt.Errorf("unable to determine if the import completed successfully - please run 'oc describe -n %s imagestream/%s' to see if the tags were updated as expected: %v", stream.Namespace, stream.Name, err) } fmt.Fprint(cmd.Out(), "The import completed successfully.", "\n\n") d := describe.ImageStreamDescriber{Interface: osClient} info, err := d.Describe(stream.Namespace, stream.Name) if err != nil { return err } fmt.Fprintln(out, info) return nil }
// RunImportImage contains all the necessary functionality for the OpenShift cli import-image command. func RunImportImage(f *clientcmd.Factory, out io.Writer, cmd *cobra.Command, args []string) error { if len(args) == 0 || len(args[0]) == 0 { return cmdutil.UsageError(cmd, "you must specify the name of an image stream") } target := args[0] namespace, _, err := f.DefaultNamespace() if err != nil { return err } osClient, _, err := f.Clients() if err != nil { return err } insecure := cmdutil.GetFlagBool(cmd, "insecure") from := cmdutil.GetFlagString(cmd, "from") confirm := cmdutil.GetFlagBool(cmd, "confirm") all := cmdutil.GetFlagBool(cmd, "all") targetRef, err := imageapi.ParseDockerImageReference(target) switch { case err != nil: return fmt.Errorf("the image name must be a valid Docker image pull spec or reference to an image stream (e.g. myregistry/myteam/image:tag)") case len(targetRef.ID) > 0: return fmt.Errorf("to import images by ID, use the 'tag' command") case len(targetRef.Tag) != 0 && all: // error out return fmt.Errorf("cannot specify a tag %q as well as --all", target) case len(targetRef.Tag) == 0 && !all: // apply the default tag targetRef.Tag = imageapi.DefaultImageTag } name := targetRef.Name tag := targetRef.Tag imageStreamClient := osClient.ImageStreams(namespace) stream, err := imageStreamClient.Get(name) if err != nil { if !errors.IsNotFound(err) { return err } // the stream is new if !confirm { return fmt.Errorf("no image stream named %q exists, pass --confirm to create and import", name) } if len(from) == 0 { from = target } if all { stream = &imageapi.ImageStream{ ObjectMeta: kapi.ObjectMeta{Name: name}, Spec: imageapi.ImageStreamSpec{DockerImageRepository: from}, } } else { stream = &imageapi.ImageStream{ ObjectMeta: kapi.ObjectMeta{Name: name}, Spec: imageapi.ImageStreamSpec{ Tags: map[string]imageapi.TagReference{ tag: { From: &kapi.ObjectReference{ Kind: "DockerImage", Name: from, }, }, }, }, } } } else { // the stream already exists if len(stream.Spec.DockerImageRepository) == 0 && len(stream.Spec.Tags) == 0 { return fmt.Errorf("image stream has not defined anything to import") } if all { // importing a whole repository if len(from) == 0 { from = target } if from != stream.Spec.DockerImageRepository { if !confirm { if len(stream.Spec.DockerImageRepository) == 0 { return fmt.Errorf("the image stream does not currently import an entire Docker repository, pass --confirm to update") } return fmt.Errorf("the image stream has a different import spec %q, pass --confirm to update", stream.Spec.DockerImageRepository) } stream.Spec.DockerImageRepository = from } } else { // importing a single tag // follow any referential tags to the destination finalTag, existing, ok, multiple := imageapi.FollowTagReference(stream, tag) if !ok && multiple { return fmt.Errorf("tag %q on the image stream is a reference to %q, which does not exist", tag, finalTag) } if ok { // disallow changing an existing tag if existing.From == nil || existing.From.Kind != "DockerImage" { return fmt.Errorf("tag %q already exists - you must use the 'tag' command if you want to change the source to %q", tag, from) } if len(from) != 0 && from != existing.From.Name { if multiple { return fmt.Errorf("the tag %q points to the tag %q which points to %q - use the 'tag' command if you want to change the source to %q", tag, finalTag, existing.From.Name, from) } return fmt.Errorf("the tag %q points to %q - use the 'tag' command if you want to change the source to %q", tag, existing.From.Name, from) } // set the target item to import from = existing.From.Name if multiple { tag = finalTag } // clear the legacy annotation delete(existing.Annotations, imageapi.DockerImageRepositoryCheckAnnotation) // reset the generation zero := int64(0) existing.Generation = &zero } else { // create a new tag if len(from) == 0 { from = target } existing = &imageapi.TagReference{ From: &kapi.ObjectReference{ Kind: "DockerImage", Name: from, }, } } stream.Spec.Tags[tag] = *existing } } if len(from) == 0 { // catch programmer error return fmt.Errorf("unexpected error, from is empty") } // Attempt the new, direct import path isi := &imageapi.ImageStreamImport{ ObjectMeta: kapi.ObjectMeta{ Name: stream.Name, Namespace: namespace, ResourceVersion: stream.ResourceVersion, }, Spec: imageapi.ImageStreamImportSpec{Import: true}, } if all { isi.Spec.Repository = &imageapi.RepositoryImportSpec{ From: kapi.ObjectReference{ Kind: "DockerImage", Name: from, }, ImportPolicy: imageapi.TagImportPolicy{Insecure: insecure}, } } else { isi.Spec.Images = append(isi.Spec.Images, imageapi.ImageImportSpec{ From: kapi.ObjectReference{ Kind: "DockerImage", Name: from, }, To: &kapi.LocalObjectReference{Name: tag}, ImportPolicy: imageapi.TagImportPolicy{Insecure: insecure}, }) } // TODO: add dry-run _, err = imageStreamClient.Import(isi) switch { case err == client.ErrImageStreamImportUnsupported: case err != nil: return err default: fmt.Fprint(cmd.Out(), "The import completed successfully.\n\n") // optimization, use the image stream returned by the call d := describe.ImageStreamDescriber{Interface: osClient} info, err := d.Describe(namespace, stream.Name) if err != nil { return err } fmt.Fprintln(out, info) return nil } // Legacy path, remove when support for older importers is removed delete(stream.Annotations, imageapi.DockerImageRepositoryCheckAnnotation) if insecure { if stream.Annotations == nil { stream.Annotations = make(map[string]string) } stream.Annotations[imageapi.InsecureRepositoryAnnotation] = "true" } if stream.CreationTimestamp.IsZero() { stream, err = imageStreamClient.Create(stream) } else { stream, err = imageStreamClient.Update(stream) } if err != nil { return err } resourceVersion := stream.ResourceVersion fmt.Fprintln(cmd.Out(), "Importing (ctrl+c to stop waiting) ...") updatedStream, err := waitForImport(imageStreamClient, stream.Name, resourceVersion) if err != nil { if _, ok := err.(importError); ok { return err } return fmt.Errorf("unable to determine if the import completed successfully - please run 'oc describe -n %s imagestream/%s' to see if the tags were updated as expected: %v", stream.Namespace, stream.Name, err) } fmt.Fprint(cmd.Out(), "The import completed successfully.\n\n") d := describe.ImageStreamDescriber{Interface: osClient} info, err := d.Describe(updatedStream.Namespace, updatedStream.Name) if err != nil { return err } fmt.Fprintln(out, info) return nil }
// Run contains all the necessary functionality for the OpenShift cli import-image command. func (o *ImportImageOptions) Run() error { // TODO: add dry-run stream, isi, err := o.createImageImport() if err != nil { return err } // Attempt the new, direct import path result, err := o.isClient.Import(isi) switch { case err == client.ErrImageStreamImportUnsupported: case err != nil: return err default: fmt.Fprint(o.out, "The import completed successfully.\n\n") // optimization, use the image stream returned by the call d := describe.ImageStreamDescriber{Interface: o.osClient} info, err := d.Describe(o.Namespace, stream.Name, kctl.DescriberSettings{}) if err != nil { return err } fmt.Fprintln(o.out, info) if r := result.Status.Repository; r != nil && len(r.AdditionalTags) > 0 { fmt.Fprintf(o.out, "\ninfo: The remote repository contained %d additional tags which were not imported: %s\n", len(r.AdditionalTags), strings.Join(r.AdditionalTags, ", ")) } return nil } // Legacy path, remove when support for older importers is removed delete(stream.Annotations, imageapi.DockerImageRepositoryCheckAnnotation) if o.Insecure != nil && *o.Insecure { if stream.Annotations == nil { stream.Annotations = make(map[string]string) } stream.Annotations[imageapi.InsecureRepositoryAnnotation] = "true" } if stream.CreationTimestamp.IsZero() { stream, err = o.isClient.Create(stream) } else { stream, err = o.isClient.Update(stream) } if err != nil { return err } fmt.Fprintln(o.out, "Importing (ctrl+c to stop waiting) ...") resourceVersion := stream.ResourceVersion updatedStream, err := o.waitForImport(resourceVersion) if err != nil { if _, ok := err.(importError); ok { return err } return fmt.Errorf("unable to determine if the import completed successfully - please run 'oc describe -n %s imagestream/%s' to see if the tags were updated as expected: %v", stream.Namespace, stream.Name, err) } fmt.Fprint(o.out, "The import completed successfully.\n\n") d := describe.ImageStreamDescriber{Interface: o.osClient} info, err := d.Describe(updatedStream.Namespace, updatedStream.Name, kctl.DescriberSettings{}) if err != nil { return err } fmt.Fprintln(o.out, info) return nil }