// Create registers a new image (if it doesn't exist) and updates the specified ImageStream's tags. func (s *REST) Create(ctx kapi.Context, obj runtime.Object) (runtime.Object, error) { if err := rest.BeforeCreate(Strategy, ctx, obj); err != nil { return nil, err } mapping := obj.(*api.ImageStreamMapping) stream, err := s.findStreamForMapping(ctx, mapping) if err != nil { return nil, err } image := mapping.Image tag := mapping.Tag if len(tag) == 0 { tag = api.DefaultImageTag } if err := s.imageRegistry.CreateImage(ctx, &image); err != nil && !errors.IsAlreadyExists(err) { return nil, err } next := api.TagEvent{ Created: util.Now(), DockerImageReference: image.DockerImageReference, Image: image.Name, } if !api.AddTagEventToImageStream(stream, tag, next) { // nothing actually changed return &kapi.Status{Status: kapi.StatusSuccess}, nil } api.UpdateTrackingTags(stream, tag, next) if _, err := s.imageStreamRegistry.UpdateImageStreamStatus(ctx, stream); err != nil { return nil, err } return &kapi.Status{Status: kapi.StatusSuccess}, nil }
// tagsChanged updates stream.Status.Tags based on the old and new image stream. // if the old stream is nil, all tags are considered additions. func (s Strategy) tagsChanged(old, stream *api.ImageStream) fielderrors.ValidationErrorList { var errs fielderrors.ValidationErrorList oldTags := map[string]api.TagReference{} if old != nil && old.Spec.Tags != nil { oldTags = old.Spec.Tags } for tag, tagRef := range stream.Spec.Tags { if oldRef, ok := oldTags[tag]; ok && !tagRefChanged(oldRef, tagRef, stream.Namespace) { continue } if tagRef.From == nil { continue } if tagRef.From.Kind == "DockerImage" && len(tagRef.From.Name) > 0 { event, err := tagReferenceToTagEvent(stream, tagRef, "") if err != nil { errs = append(errs, fielderrors.NewFieldInvalid(fmt.Sprintf("spec.tags[%s].from", tag), tagRef.From, err.Error())) continue } api.AddTagEventToImageStream(stream, tag, *event) continue } tagRefStreamName, tagOrID, err := parseFromReference(stream, tagRef.From) if err != nil { errs = append(errs, fielderrors.NewFieldInvalid(fmt.Sprintf("spec.tags[%s].from.name", tag), tagRef.From.Name, "must be of the form <tag>, <repo>:<tag>, <id>, or <repo>@<id>")) continue } streamRef := stream streamRefNamespace := tagRef.From.Namespace if len(streamRefNamespace) == 0 { streamRefNamespace = stream.Namespace } if streamRefNamespace != stream.Namespace || tagRefStreamName != stream.Name { obj, err := s.ImageStreamGetter.Get(kapi.WithNamespace(kapi.NewContext(), streamRefNamespace), tagRefStreamName) if err != nil { errs = append(errs, fielderrors.NewFieldInvalid(fmt.Sprintf("spec.tags[%s].from.name", tag), tagRef.From.Name, fmt.Sprintf("error retrieving ImageStream %s/%s: %v", streamRefNamespace, tagRefStreamName, err))) continue } streamRef = obj.(*api.ImageStream) } event, err := tagReferenceToTagEvent(streamRef, tagRef, tagOrID) if err != nil { errs = append(errs, fielderrors.NewFieldInvalid(fmt.Sprintf("spec.tags[%s].from.name", tag), tagRef.From.Name, fmt.Sprintf("error generating tag event: %v", err))) continue } if event == nil { util.HandleError(fmt.Errorf("unable to find tag event for %#v", tagRef.From)) continue } api.AddTagEventToImageStream(stream, tag, *event) } // use a consistent timestamp on creation if old == nil && !stream.CreationTimestamp.IsZero() { for tag, list := range stream.Status.Tags { for _, event := range list.Items { event.Created = stream.CreationTimestamp } stream.Status.Tags[tag] = list } } return errs }