func tagReferenceToTagEvent(stream *api.ImageStream, tagRef api.TagReference, tagOrID string) (*api.TagEvent, error) { var ( event *api.TagEvent err error ) switch tagRef.From.Kind { case "DockerImage": event = &api.TagEvent{ Created: unversioned.Now(), DockerImageReference: tagRef.From.Name, } case "ImageStreamImage": event, err = api.ResolveImageID(stream, tagOrID) case "ImageStreamTag": event, err = api.LatestTaggedImage(stream, tagOrID), nil default: err = fmt.Errorf("invalid from.kind %q: it must be DockerImage, ImageStreamImage or ImageStreamTag", tagRef.From.Kind) } if err != nil { return nil, err } if event != nil && tagRef.Generation != nil { event.Generation = *tagRef.Generation } return event, nil }
func autoConvert_v1_TagEvent_To_api_TagEvent(in *TagEvent, out *api.TagEvent, s conversion.Scope) error { out.Created = in.Created out.DockerImageReference = in.DockerImageReference out.Image = in.Image out.Generation = in.Generation return nil }
func autoConvert_v1_TagEvent_To_api_TagEvent(in *TagEvent, out *api.TagEvent, s conversion.Scope) error { if err := pkg_api.Convert_unversioned_Time_To_unversioned_Time(&in.Created, &out.Created, s); err != nil { return err } out.DockerImageReference = in.DockerImageReference out.Image = in.Image out.Generation = in.Generation return nil }
func autoConvert_v1_TagEvent_To_api_TagEvent(in *TagEvent, out *image_api.TagEvent, s conversion.Scope) error { if defaulting, found := s.DefaultingInterface(reflect.TypeOf(*in)); found { defaulting.(func(*TagEvent))(in) } if err := api.Convert_unversioned_Time_To_unversioned_Time(&in.Created, &out.Created, s); err != nil { return err } out.DockerImageReference = in.DockerImageReference out.Image = in.Image out.Generation = in.Generation return nil }
// Create registers a new image (if it doesn't exist) and updates the // specified ImageStream's tags. If attempts to update the ImageStream fail // with a resource conflict, the update will be retried if the newer // ImageStream has no tag diffs from the previous state. If tag diffs are // detected, the conflict error is returned. 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: unversioned.Now(), DockerImageReference: image.DockerImageReference, Image: image.Name, } err = wait.ExponentialBackoff(wait.Backoff{Steps: maxRetriesOnConflict}, func() (bool, error) { lastEvent := api.LatestTaggedImage(stream, tag) next.Generation = stream.Generation if !api.AddTagEventToImageStream(stream, tag, next) { // nothing actually changed return true, nil } api.UpdateTrackingTags(stream, tag, next) _, err := s.imageStreamRegistry.UpdateImageStreamStatus(ctx, stream) if err == nil { return true, nil } if !errors.IsConflict(err) { return false, err } // If the update conflicts, get the latest stream and check for tag // updates. If the latest tag hasn't changed, retry. latestStream, findLatestErr := s.findStreamForMapping(ctx, mapping) if findLatestErr != nil { return false, findLatestErr } // no previous tag if lastEvent == nil { // The tag hasn't changed, so try again with the updated stream. stream = latestStream return false, nil } // check for tag change newerEvent := api.LatestTaggedImage(latestStream, tag) // generation and creation time differences are ignored lastEvent.Generation = newerEvent.Generation lastEvent.Created = newerEvent.Created if kapi.Semantic.DeepEqual(lastEvent, newerEvent) { // The tag hasn't changed, so try again with the updated stream. stream = latestStream return false, nil } // The tag changed, so return the conflict error back to the client. return false, err }) if err != nil { return nil, err } return &unversioned.Status{Status: unversioned.StatusSuccess}, nil }