// Create a LimitRange object func (rs *REST) Create(ctx api.Context, obj runtime.Object) (runtime.Object, error) { limitRange, ok := obj.(*api.LimitRange) if !ok { return nil, fmt.Errorf("invalid object type") } if !api.ValidNamespace(ctx, &limitRange.ObjectMeta) { return nil, errors.NewConflict("limitRange", limitRange.Namespace, fmt.Errorf("LimitRange.Namespace does not match the provided context")) } if len(limitRange.Name) == 0 { limitRange.Name = string(util.NewUUID()) } if errs := validation.ValidateLimitRange(limitRange); len(errs) > 0 { return nil, errors.NewInvalid("limitRange", limitRange.Name, errs) } api.FillObjectMetaSystemFields(ctx, &limitRange.ObjectMeta) err := rs.registry.CreateWithName(ctx, limitRange.Name, limitRange) if err != nil { return nil, err } return rs.registry.Get(ctx, limitRange.Name) }
// BeforeCreate ensures that common operations for all resources are performed on creation. It only returns // errors that can be converted to api.Status. It invokes PrepareForCreate, then GenerateName, then Validate. // It returns nil if the object should be created. func BeforeCreate(strategy RESTCreateStrategy, ctx api.Context, obj runtime.Object) error { objectMeta, kind, kerr := objectMetaAndKind(strategy, obj) if kerr != nil { return kerr } if strategy.NamespaceScoped() { if !api.ValidNamespace(ctx, objectMeta) { return errors.NewBadRequest("the namespace of the provided object does not match the namespace sent on the request") } } else { objectMeta.Namespace = api.NamespaceNone } objectMeta.DeletionTimestamp = nil objectMeta.DeletionGracePeriodSeconds = nil strategy.PrepareForCreate(obj) api.FillObjectMetaSystemFields(ctx, objectMeta) api.GenerateName(strategy, objectMeta) if errs := strategy.Validate(ctx, obj); len(errs) > 0 { return errors.NewInvalid(kind, objectMeta.Name, errs) } // Custom validation (including name validation) passed // Now run common validation on object meta // Do this *after* custom validation so that specific error messages are shown whenever possible if errs := validation.ValidateObjectMeta(objectMeta, strategy.NamespaceScoped(), validation.ValidatePathSegmentName); len(errs) > 0 { return errors.NewInvalid(kind, objectMeta.Name, errs) } strategy.Canonicalize(obj) return nil }
// TestFillObjectMetaSystemFields validates that system populated fields are set on an object func TestFillObjectMetaSystemFields(t *testing.T) { ctx := api.NewDefaultContext() resource := api.ObjectMeta{} api.FillObjectMetaSystemFields(ctx, &resource) if resource.CreationTimestamp.Time.IsZero() { t.Errorf("resource.CreationTimestamp is zero") } else if len(resource.UID) == 0 { t.Errorf("resource.UID missing") } // verify we can inject a UID uid := uuid.NewUUID() ctx = api.WithUID(ctx, uid) resource = api.ObjectMeta{} api.FillObjectMetaSystemFields(ctx, &resource) if resource.UID != uid { t.Errorf("resource.UID expected: %v, actual: %v", uid, resource.UID) } }
// TestFillObjectMetaSystemFields validates that system populated fields are set on an object func TestFillObjectMetaSystemFields(t *testing.T) { ctx := api.NewDefaultContext() resource := api.ObjectMeta{} api.FillObjectMetaSystemFields(ctx, &resource) if resource.CreationTimestamp.Time.IsZero() { t.Errorf("resource.CreationTimestamp is zero") } else if len(resource.UID) == 0 { t.Errorf("resource.UID missing") } }
// TestHasObjectMetaSystemFieldValues validates that true is returned if and only if all fields are populated func TestHasObjectMetaSystemFieldValues(t *testing.T) { ctx := api.NewDefaultContext() resource := api.ObjectMeta{} if api.HasObjectMetaSystemFieldValues(&resource) { t.Errorf("the resource does not have all fields yet populated, but incorrectly reports it does") } api.FillObjectMetaSystemFields(ctx, &resource) if !api.HasObjectMetaSystemFieldValues(&resource) { t.Errorf("the resource does have all fields populated, but incorrectly reports it does not") } }
// createBuild is responsible for validating build object and saving it and returning newly created object func (g *BuildGenerator) createBuild(ctx kapi.Context, build *buildapi.Build) (*buildapi.Build, error) { if !kapi.ValidNamespace(ctx, &build.ObjectMeta) { return nil, errors.NewConflict(buildapi.Resource("build"), build.Namespace, fmt.Errorf("Build.Namespace does not match the provided context")) } kapi.FillObjectMetaSystemFields(ctx, &build.ObjectMeta) err := g.Client.CreateBuild(ctx, build) if err != nil { return nil, err } return g.Client.GetBuild(ctx, build.Name) }
// Create registers the given Project. func (s *REST) Create(ctx kapi.Context, obj runtime.Object) (runtime.Object, error) { project, ok := obj.(*api.Project) if !ok { return nil, fmt.Errorf("not a project: %#v", obj) } kapi.FillObjectMetaSystemFields(ctx, &project.ObjectMeta) s.createStrategy.PrepareForCreate(obj) if errs := s.createStrategy.Validate(ctx, obj); len(errs) > 0 { return nil, kerrors.NewInvalid("project", project.Name, errs) } namespace, err := s.client.Create(convertProject(project)) if err != nil { return nil, err } return convertNamespace(namespace), nil }
func (rs *REST) Create(ctx api.Context, obj runtime.Object) (runtime.Object, error) { event, ok := obj.(*api.Event) if !ok { return nil, errors.NewInternalError(fmt.Errorf("received object is not of type event: %#v", obj)) } if api.NamespaceValue(ctx) != "" { if !api.ValidNamespace(ctx, &event.ObjectMeta) { return nil, errors.NewConflict("event", event.Namespace, fmt.Errorf("event.namespace does not match the provided context")) } } if errs := validation.ValidateEvent(event); len(errs) > 0 { return nil, errors.NewInvalid("event", event.Name, errs) } api.FillObjectMetaSystemFields(ctx, &event.ObjectMeta) err := rs.registry.CreateWithName(ctx, event.Name, event) if err != nil { return nil, err } return rs.registry.Get(ctx, event.Name) }
// BeforeCreate ensures that common operations for all resources are performed on creation. It only returns // errors that can be converted to api.Status. It invokes PrepareForCreate, then GenerateName, then Validate. // It returns nil if the object should be created. func BeforeCreate(strategy RESTCreateStrategy, ctx api.Context, obj runtime.Object) error { objectMeta, kind, kerr := objectMetaAndKind(strategy, obj) if kerr != nil { return kerr } if strategy.NamespaceScoped() { if !api.ValidNamespace(ctx, objectMeta) { return errors.NewBadRequest("the namespace of the provided object does not match the namespace sent on the request") } } else { objectMeta.Namespace = api.NamespaceNone } strategy.PrepareForCreate(obj) api.FillObjectMetaSystemFields(ctx, objectMeta) api.GenerateName(strategy, objectMeta) if errs := strategy.Validate(ctx, obj); len(errs) > 0 { return errors.NewInvalid(kind, objectMeta.Name, errs) } return nil }
// Create registers a given new Route instance to rs.registry. func (rs *REST) Create(ctx kapi.Context, obj runtime.Object) (runtime.Object, error) { route, ok := obj.(*api.Route) if !ok { return nil, errors.NewBadRequest(fmt.Sprintf("not a route: %#v", obj)) } if !kapi.ValidNamespace(ctx, &route.ObjectMeta) { return nil, errors.NewConflict("route", route.Namespace, fmt.Errorf("Route.Namespace does not match the provided context")) } shard, err := rs.allocator.AllocateRouterShard(route) if err != nil { return nil, errors.NewInternalError(fmt.Errorf("allocation error: %s for route: %#v", err, obj)) } if route.Annotations == nil { route.Annotations = map[string]string{} } if len(route.Host) == 0 { route.Host = rs.allocator.GenerateHostname(route, shard) route.Annotations[HostGeneratedAnnotationKey] = "true" } else { route.Annotations[HostGeneratedAnnotationKey] = "false" } if errs := validation.ValidateRoute(route); len(errs) > 0 { return nil, errors.NewInvalid("route", route.Name, errs) } if len(route.Name) == 0 { route.Name = uuid.NewUUID().String() } kapi.FillObjectMetaSystemFields(ctx, &route.ObjectMeta) err = rs.registry.CreateRoute(ctx, route) if err != nil { return nil, err } return rs.registry.GetRoute(ctx, route.Name) }
func (r *REST) Update(ctx kapi.Context, tagName string, objInfo rest.UpdatedObjectInfo) (runtime.Object, bool, error) { name, tag, err := nameAndTag(tagName) if err != nil { return nil, false, err } create := false imageStream, err := r.imageStreamRegistry.GetImageStream(ctx, name) if err != nil { if !kapierrors.IsNotFound(err) { return nil, false, err } namespace, ok := kapi.NamespaceFrom(ctx) if !ok { return nil, false, kapierrors.NewBadRequest("namespace is required on ImageStreamTags") } imageStream = &api.ImageStream{ ObjectMeta: kapi.ObjectMeta{ Namespace: namespace, Name: name, }, } kapi.FillObjectMetaSystemFields(ctx, &imageStream.ObjectMeta) create = true } // create the synthetic old istag old, err := newISTag(tag, imageStream, nil, true) if err != nil { return nil, false, err } obj, err := objInfo.UpdatedObject(ctx, old) if err != nil { return nil, false, err } istag, ok := obj.(*api.ImageStreamTag) if !ok { return nil, false, kapierrors.NewBadRequest(fmt.Sprintf("obj is not an ImageStreamTag: %#v", obj)) } // check for conflict switch { case len(istag.ResourceVersion) == 0: // should disallow blind PUT, but this was previously supported istag.ResourceVersion = imageStream.ResourceVersion case len(imageStream.ResourceVersion) == 0: // image stream did not exist, cannot update return nil, false, kapierrors.NewNotFound(api.Resource("imagestreamtags"), tagName) case imageStream.ResourceVersion != istag.ResourceVersion: // conflicting input and output return nil, false, kapierrors.NewConflict(api.Resource("imagestreamtags"), istag.Name, fmt.Errorf("another caller has updated the resource version to %s", imageStream.ResourceVersion)) } if create { if err := rest.BeforeCreate(Strategy, ctx, obj); err != nil { return nil, false, err } } else { if err := rest.BeforeUpdate(Strategy, ctx, obj, old); err != nil { return nil, false, err } } // update the spec tag if imageStream.Spec.Tags == nil { imageStream.Spec.Tags = map[string]api.TagReference{} } tagRef, exists := imageStream.Spec.Tags[tag] // if the caller set tag, override the spec tag if istag.Tag != nil { tagRef = *istag.Tag tagRef.Name = tag } tagRef.Annotations = istag.Annotations imageStream.Spec.Tags[tag] = tagRef // mutate the image stream var newImageStream *api.ImageStream if create { newImageStream, err = r.imageStreamRegistry.CreateImageStream(ctx, imageStream) } else { newImageStream, err = r.imageStreamRegistry.UpdateImageStream(ctx, imageStream) } if err != nil { return nil, false, err } image, err := r.imageFor(ctx, tag, newImageStream) if err != nil { if !kapierrors.IsNotFound(err) { return nil, false, err } } newISTag, err := newISTag(tag, newImageStream, image, true) return newISTag, !exists, err }