func TestCheckInvalidErr(t *testing.T) { tests := []struct { err error expected string }{ { errors.NewInvalid(api.Kind("Invalid1"), "invalidation", field.ErrorList{field.Invalid(field.NewPath("field"), "single", "details")}), `Error from server: Invalid1 "invalidation" is invalid: field: Invalid value: "single": details`, }, { errors.NewInvalid(api.Kind("Invalid2"), "invalidation", field.ErrorList{field.Invalid(field.NewPath("field1"), "multi1", "details"), field.Invalid(field.NewPath("field2"), "multi2", "details")}), `Error from server: Invalid2 "invalidation" is invalid: [field1: Invalid value: "multi1": details, field2: Invalid value: "multi2": details]`, }, { errors.NewInvalid(api.Kind("Invalid3"), "invalidation", field.ErrorList{}), `Error from server: Invalid3 "invalidation" is invalid: <nil>`, }, } var errReturned string errHandle := func(err string) { errReturned = err } for _, test := range tests { checkErr(test.err, errHandle) if errReturned != test.expected { t.Fatalf("Got: %s, expected: %s", errReturned, test.expected) } } }
func TestCheckInvalidErr(t *testing.T) { tests := []struct { err error expected string }{ { errors.NewInvalid("Invalid1", "invalidation", fielderrors.ValidationErrorList{fielderrors.NewFieldInvalid("Cause", "single", "details")}), `Error from server: Invalid1 "invalidation" is invalid: Cause: invalid value 'single', Details: details`, }, { errors.NewInvalid("Invalid2", "invalidation", fielderrors.ValidationErrorList{fielderrors.NewFieldInvalid("Cause", "multi1", "details"), fielderrors.NewFieldInvalid("Cause", "multi2", "details")}), `Error from server: Invalid2 "invalidation" is invalid: [Cause: invalid value 'multi1', Details: details, Cause: invalid value 'multi2', Details: details]`, }, { errors.NewInvalid("Invalid3", "invalidation", fielderrors.ValidationErrorList{}), `Error from server: Invalid3 "invalidation" is invalid: <nil>`, }, } var errReturned string errHandle := func(err string) { errReturned = err } for _, test := range tests { checkErr(test.err, errHandle) if errReturned != test.expected { t.Fatalf("Got: %s, expected: %s", errReturned, test.expected) } } }
// Create processes a Template and creates a new list of objects func (s *REST) Create(ctx kapi.Context, obj runtime.Object) (runtime.Object, error) { tpl, ok := obj.(*api.Template) if !ok { return nil, errors.NewBadRequest("not a template") } if errs := templatevalidation.ValidateProcessedTemplate(tpl); len(errs) > 0 { return nil, errors.NewInvalid(api.Kind("Template"), tpl.Name, errs) } generators := map[string]generator.Generator{ "expression": generator.NewExpressionValueGenerator(rand.New(rand.NewSource(time.Now().UnixNano()))), } processor := template.NewProcessor(generators) if errs := processor.Process(tpl); len(errs) > 0 { glog.V(1).Infof(errs.ToAggregate().Error()) return nil, errors.NewInvalid(api.Kind("Template"), tpl.Name, errs) } // we know that we get back runtime.Unstructured objects from the Process call. We need to encode those // objects using the unstructured codec BEFORE the REST layers gets its shot at encoding to avoid a layered // encode being done. for i := range tpl.Objects { tpl.Objects[i] = runtime.NewEncodable(runtime.UnstructuredJSONScheme, tpl.Objects[i]) } return tpl, nil }
// 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 }
// Create ensures a pod is bound to a specific host. func (r *BindingREST) Create(ctx api.Context, obj runtime.Object) (out runtime.Object, err error) { binding := obj.(*api.Binding) // TODO: move me to a binding strategy if len(binding.Target.Kind) != 0 && binding.Target.Kind != "Node" { return nil, errors.NewInvalid("binding", binding.Name, validation.ErrorList{validation.NewInvalidError("to.kind", binding.Target.Kind, "must be empty or 'Node'")}) } if len(binding.Target.Name) == 0 { return nil, errors.NewInvalid("binding", binding.Name, validation.ErrorList{validation.NewRequiredError("to.name")}) } err = r.assignPod(ctx, binding.Name, binding.Target.Name, binding.Annotations) out = &unversioned.Status{Status: unversioned.StatusSuccess} return }
// Create ensures a pod is bound to a specific host. func (r *BindingREST) Create(ctx api.Context, obj runtime.Object) (out runtime.Object, err error) { binding := obj.(*api.Binding) // TODO: move me to a binding strategy if len(binding.Target.Kind) != 0 && (binding.Target.Kind != "Node" && binding.Target.Kind != "Minion") { return nil, errors.NewInvalid("binding", binding.Name, fielderrors.ValidationErrorList{fielderrors.NewFieldInvalid("to.kind", binding.Target.Kind, "must be empty, 'Node', or 'Minion'")}) } if len(binding.Target.Name) == 0 { return nil, errors.NewInvalid("binding", binding.Name, fielderrors.ValidationErrorList{fielderrors.NewFieldRequired("to.name")}) } err = r.assignPod(ctx, binding.Name, binding.Target.Name, binding.Annotations) out = &api.Status{Status: api.StatusSuccess} return }
func TestCheckInvalidErr(t *testing.T) { tests := []struct { err error expected string }{ { errors.NewInvalid(api.Kind("Invalid1"), "invalidation", field.ErrorList{field.Invalid(field.NewPath("field"), "single", "details")}), `error: The Invalid1 "invalidation" is invalid. field: Invalid value: "single": details`, }, { errors.NewInvalid(api.Kind("Invalid2"), "invalidation", field.ErrorList{field.Invalid(field.NewPath("field1"), "multi1", "details"), field.Invalid(field.NewPath("field2"), "multi2", "details")}), `error: The Invalid2 "invalidation" is invalid. * field1: Invalid value: "multi1": details, * field2: Invalid value: "multi2": details`, }, { errors.NewInvalid(api.Kind("Invalid3"), "invalidation", field.ErrorList{}), `error: The Invalid3 "invalidation" is invalid. %!s(<nil>)`, }, { errors.NewInvalid(api.Kind("Invalid4"), "invalidation", field.ErrorList{field.Invalid(field.NewPath("field4"), "multi4", "details"), field.Invalid(field.NewPath("field4"), "multi4", "details")}), `error: The Invalid4 "invalidation" is invalid. field4: Invalid value: "multi4": details`, }, } var errReturned string errHandle := func(err string) { for _, v := range strings.Split(err, "\n") { separator := " " if errReturned == "" || v == "" { separator = "" } else if !strings.HasSuffix(errReturned, ".") { separator = ", " } errReturned = fmt.Sprintf("%s%s%s", errReturned, separator, v) } if !strings.HasPrefix(errReturned, "error: ") { errReturned = fmt.Sprintf("error: %s", errReturned) } if strings.HasSuffix(errReturned, ", ") { errReturned = errReturned[:len(errReturned)-len(" ,")] } } for _, test := range tests { checkErr(test.err, errHandle) if errReturned != test.expected { t.Fatalf("Got: %s, expected: %s", errReturned, test.expected) } errReturned = "" } }
// Create ensures a pod is bound to a specific host. func (r *BindingREST) Create(ctx api.Context, obj runtime.Object) (out runtime.Object, err error) { glog.Info("pkg/registry/pod/etcd/etcd.go #Create") binding := obj.(*api.Binding) // TODO: move me to a binding strategy if len(binding.Target.Kind) != 0 && binding.Target.Kind != "Node" { return nil, errors.NewInvalid("binding", binding.Name, fielderrors.ValidationErrorList{fielderrors.NewFieldInvalid("to.kind", binding.Target.Kind, "must be empty, 'Node', or 'Minion'")}) } if len(binding.Target.Name) == 0 { return nil, errors.NewInvalid("binding", binding.Name, fielderrors.ValidationErrorList{fielderrors.NewFieldRequired("to.name")}) } err = r.assignPod(ctx, binding.Name, binding.Target.Name, binding.Annotations) glog.Infof("%s %s", binding.Name, binding.Target.Name) out = &unversioned.Status{Status: unversioned.StatusSuccess} return }
// Create ensures a pod is bound to a specific host. func (r *BindingREST) Create(ctx api.Context, obj runtime.Object) (out runtime.Object, err error) { binding := obj.(*api.Binding) // TODO: move me to a binding strategy if len(binding.Target.Kind) != 0 && binding.Target.Kind != "Node" { // TODO: When validation becomes versioned, this gets more complicated. return nil, errors.NewInvalid("binding", binding.Name, field.ErrorList{field.NotSupported(field.NewPath("target", "kind"), binding.Target.Kind, []string{"Node", "<empty>"})}) } if len(binding.Target.Name) == 0 { // TODO: When validation becomes versioned, this gets more complicated. return nil, errors.NewInvalid("binding", binding.Name, field.ErrorList{field.Required(field.NewPath("target", "name"))}) } err = r.assignPod(ctx, binding.Name, binding.Target.Name, binding.Annotations) out = &unversioned.Status{Status: unversioned.StatusSuccess} return }
// Admit determines if the service should be admitted based on the configured network CIDR. func (r *externalIPRanger) Admit(a kadmission.Attributes) error { if a.GetResource() != kapi.Resource("services") { return nil } svc, ok := a.GetObject().(*kapi.Service) // if we can't convert then we don't handle this object so just return if !ok { return nil } var errs field.ErrorList switch { // administrator disabled externalIPs case len(svc.Spec.ExternalIPs) > 0 && len(r.admit) == 0: errs = append(errs, field.Forbidden(field.NewPath("spec", "externalIPs"), "externalIPs have been disabled")) // administrator has limited the range case len(svc.Spec.ExternalIPs) > 0 && len(r.admit) > 0: for i, s := range svc.Spec.ExternalIPs { ip := net.ParseIP(s) if ip == nil { errs = append(errs, field.Forbidden(field.NewPath("spec", "externalIPs").Index(i), "externalIPs must be a valid address")) continue } if networkSlice(r.reject).Contains(ip) || !networkSlice(r.admit).Contains(ip) { errs = append(errs, field.Forbidden(field.NewPath("spec", "externalIPs").Index(i), "externalIP is not allowed")) continue } } } if len(errs) > 0 { return apierrs.NewInvalid(a.GetKind(), a.GetName(), errs) } return nil }
// Create transforms a LocalSAR into an ClusterSAR that is requesting a namespace. That collapses the code paths. // LocalSubjectAccessReview exists to allow clean expression of policy. func (r *REST) Create(ctx kapi.Context, obj runtime.Object) (runtime.Object, error) { localSAR, ok := obj.(*authorizationapi.LocalSubjectAccessReview) if !ok { return nil, kapierrors.NewBadRequest(fmt.Sprintf("not a localSubjectAccessReview: %#v", obj)) } if errs := authorizationvalidation.ValidateLocalSubjectAccessReview(localSAR); len(errs) > 0 { return nil, kapierrors.NewInvalid(authorizationapi.Kind(localSAR.Kind), "", errs) } if namespace := kapi.NamespaceValue(ctx); len(namespace) == 0 { return nil, kapierrors.NewBadRequest(fmt.Sprintf("namespace is required on this type: %v", namespace)) } else if (len(localSAR.Action.Namespace) > 0) && (namespace != localSAR.Action.Namespace) { return nil, field.Invalid(field.NewPath("namespace"), localSAR.Action.Namespace, fmt.Sprintf("namespace must be: %v", namespace)) } // transform this into a SubjectAccessReview clusterSAR := &authorizationapi.SubjectAccessReview{ Action: localSAR.Action, User: localSAR.User, Groups: localSAR.Groups, Scopes: localSAR.Scopes, } clusterSAR.Action.Namespace = kapi.NamespaceValue(ctx) return r.clusterSARRegistry.CreateSubjectAccessReview(kapi.WithNamespace(ctx, ""), clusterSAR) }
func (r *ScaleREST) Update(ctx api.Context, obj runtime.Object) (runtime.Object, bool, error) { if obj == nil { return nil, false, errors.NewBadRequest(fmt.Sprintf("nil update passed to Scale")) } scale, ok := obj.(*extensions.Scale) if !ok { return nil, false, errors.NewBadRequest(fmt.Sprintf("expected input object type to be Scale, but %T", obj)) } if errs := extvalidation.ValidateScale(scale); len(errs) > 0 { return nil, false, errors.NewInvalid(extensions.Kind("Scale"), scale.Name, errs) } deployment, err := r.registry.GetDeployment(ctx, scale.Name) if err != nil { return nil, false, errors.NewNotFound(extensions.Resource("deployments/scale"), scale.Name) } deployment.Spec.Replicas = scale.Spec.Replicas deployment.ResourceVersion = scale.ResourceVersion deployment, err = r.registry.UpdateDeployment(ctx, deployment) if err != nil { return nil, false, err } newScale, err := scaleFromDeployment(deployment) if err != nil { return nil, false, errors.NewBadRequest(fmt.Sprintf("%v", err)) } return newScale, false, nil }
// Update scales the DeploymentConfig for the given Scale subresource, returning the updated Scale. func (r *ScaleREST) Update(ctx kapi.Context, obj runtime.Object) (runtime.Object, bool, error) { if obj == nil { return nil, false, errors.NewBadRequest(fmt.Sprintf("nil update passed to Scale")) } scale, ok := obj.(*extensions.Scale) if !ok { return nil, false, errors.NewBadRequest(fmt.Sprintf("wrong object passed to Scale update: %v", obj)) } // fake an existing object to validate existing := &extensions.Scale{ ObjectMeta: kapi.ObjectMeta{ Name: scale.Name, CreationTimestamp: scale.CreationTimestamp, }, } if existing.Namespace, ok = kapi.NamespaceFrom(ctx); !ok { existing.Namespace = scale.Namespace } if errs := extvalidation.ValidateScaleUpdate(scale, existing); len(errs) > 0 { return nil, false, errors.NewInvalid("scale", scale.Name, errs) } deploymentConfig, err := r.registry.GetDeploymentConfig(ctx, scale.Name) if err != nil { return nil, false, errors.NewNotFound("scale", scale.Name) } scaleRet := &extensions.Scale{ ObjectMeta: kapi.ObjectMeta{ Name: deploymentConfig.Name, Namespace: deploymentConfig.Namespace, CreationTimestamp: deploymentConfig.CreationTimestamp, }, Spec: extensions.ScaleSpec{ Replicas: scale.Spec.Replicas, }, Status: extensions.ScaleStatus{ Selector: deploymentConfig.Spec.Selector, }, } // TODO(directxman12): this is going to be a bit out of sync, since we are calculating it // here and not as part of the deploymentconfig loop -- is there a better way of doing it? totalReplicas, err := r.replicasForDeploymentConfig(deploymentConfig.Namespace, deploymentConfig.Name) if err != nil { return nil, false, err } oldReplicas := deploymentConfig.Spec.Replicas deploymentConfig.Spec.Replicas = scale.Spec.Replicas if err := r.registry.UpdateDeploymentConfig(ctx, deploymentConfig); err != nil { return nil, false, err } scaleRet.Status.Replicas = totalReplicas + (scale.Spec.Replicas - oldReplicas) return scaleRet, false, nil }
// Update replaces a given Route instance with an existing instance in rs.registry. func (rs *REST) Update(ctx kapi.Context, obj runtime.Object) (runtime.Object, bool, error) { route, ok := obj.(*api.Route) if !ok { return nil, false, errors.NewBadRequest(fmt.Sprintf("not a route: %#v", obj)) } if !kapi.ValidNamespace(ctx, &route.ObjectMeta) { return nil, false, errors.NewConflict("route", route.Namespace, fmt.Errorf("Route.Namespace does not match the provided context")) } old, err := rs.Get(ctx, route.Name) if err != nil { return nil, false, err } if errs := validation.ValidateRouteUpdate(route, old.(*api.Route)); len(errs) > 0 { return nil, false, errors.NewInvalid("route", route.Name, errs) } // TODO: Convert to generic etcd // TODO: Call ValidateRouteUpdate->ValidateObjectMetaUpdate // TODO: In the UpdateStrategy.PrepareForUpdate, set the HostGeneratedAnnotationKey annotation to "false" if the updated route object modifies the host err = rs.registry.UpdateRoute(ctx, route) if err != nil { return nil, false, err } out, err := rs.registry.GetRoute(ctx, route.Name) return out, false, err }
func (r *ScaleREST) Update(ctx api.Context, obj runtime.Object) (runtime.Object, bool, error) { if obj == nil { return nil, false, errors.NewBadRequest(fmt.Sprintf("nil update passed to Scale")) } scale, ok := obj.(*extensions.Scale) if !ok { return nil, false, errors.NewBadRequest(fmt.Sprintf("wrong object passed to Scale update: %v", obj)) } if errs := extvalidation.ValidateScale(scale); len(errs) > 0 { return nil, false, errors.NewInvalid(extensions.Kind("Scale"), scale.Name, errs) } rc, err := (*r.registry).GetController(ctx, scale.Name) if err != nil { return nil, false, errors.NewNotFound(extensions.Resource("replicationcontrollers/scale"), scale.Name) } rc.Spec.Replicas = scale.Spec.Replicas rc.ResourceVersion = scale.ResourceVersion rc, err = (*r.registry).UpdateController(ctx, rc) if err != nil { return nil, false, errors.NewConflict(extensions.Resource("replicationcontrollers/scale"), scale.Name, err) } return scaleFromRC(rc), false, nil }
// Update scales the DeploymentConfig for the given Scale subresource, returning the updated Scale. func (r *ScaleREST) Update(ctx kapi.Context, name string, objInfo rest.UpdatedObjectInfo) (runtime.Object, bool, error) { deploymentConfig, err := r.registry.GetDeploymentConfig(ctx, name) if err != nil { return nil, false, errors.NewNotFound(extensions.Resource("scale"), name) } old := api.ScaleFromConfig(deploymentConfig) obj, err := objInfo.UpdatedObject(ctx, old) if err != nil { return nil, false, err } scale, ok := obj.(*extensions.Scale) if !ok { return nil, false, errors.NewBadRequest(fmt.Sprintf("wrong object passed to Scale update: %v", obj)) } if errs := extvalidation.ValidateScale(scale); len(errs) > 0 { return nil, false, errors.NewInvalid(extensions.Kind("Scale"), scale.Name, errs) } deploymentConfig.Spec.Replicas = scale.Spec.Replicas if err := r.registry.UpdateDeploymentConfig(ctx, deploymentConfig); err != nil { return nil, false, err } return scale, false, nil }
// Update updates a LimitRange object. func (rs *REST) Update(ctx api.Context, obj runtime.Object) (runtime.Object, bool, error) { limitRange, ok := obj.(*api.LimitRange) if !ok { return nil, false, fmt.Errorf("invalid object type") } if !api.ValidNamespace(ctx, &limitRange.ObjectMeta) { return nil, false, errors.NewConflict("limitRange", limitRange.Namespace, fmt.Errorf("LimitRange.Namespace does not match the provided context")) } oldObj, err := rs.registry.Get(ctx, limitRange.Name) if err != nil { return nil, false, err } editLimitRange := oldObj.(*api.LimitRange) // set the editable fields on the existing object editLimitRange.Labels = limitRange.Labels editLimitRange.ResourceVersion = limitRange.ResourceVersion editLimitRange.Annotations = limitRange.Annotations editLimitRange.Spec = limitRange.Spec if errs := validation.ValidateLimitRange(editLimitRange); len(errs) > 0 { return nil, false, errors.NewInvalid("limitRange", editLimitRange.Name, errs) } if err := rs.registry.UpdateWithName(ctx, editLimitRange.Name, editLimitRange); err != nil { return nil, false, err } out, err := rs.registry.Get(ctx, editLimitRange.Name) return out, false, err }
// 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) }
// Create registers a given new ResourceAccessReview instance to r.registry. func (r *REST) Create(ctx kapi.Context, obj runtime.Object) (runtime.Object, error) { resourceAccessReview, ok := obj.(*authorizationapi.ResourceAccessReview) if !ok { return nil, kapierrors.NewBadRequest(fmt.Sprintf("not a resourceAccessReview: %#v", obj)) } if errs := authorizationvalidation.ValidateResourceAccessReview(resourceAccessReview); len(errs) > 0 { return nil, kapierrors.NewInvalid(authorizationapi.Kind(resourceAccessReview.Kind), "", errs) } // if a namespace is present on the request, then the namespace on the on the RAR is overwritten. // This is to support backwards compatibility. To have gotten here in this state, it means that // the authorizer decided that a user could run an RAR against this namespace if namespace := kapi.NamespaceValue(ctx); len(namespace) > 0 { resourceAccessReview.Action.Namespace = namespace } else if err := r.isAllowed(ctx, resourceAccessReview); err != nil { // this check is mutually exclusive to the condition above. localSAR and localRAR both clear the namespace before delegating their calls // We only need to check if the RAR is allowed **again** if the authorizer didn't already approve the request for a legacy call. return nil, err } requestContext := kapi.WithNamespace(ctx, resourceAccessReview.Action.Namespace) attributes := authorizer.ToDefaultAuthorizationAttributes(resourceAccessReview.Action) users, groups, err := r.authorizer.GetAllowedSubjects(requestContext, attributes) response := &authorizationapi.ResourceAccessReviewResponse{ Namespace: resourceAccessReview.Action.Namespace, Users: users, Groups: groups, } if err != nil { response.EvaluationError = err.Error() } return response, nil }
func (r *REST) Create(ctx api.Context, obj runtime.Object) (runtime.Object, error) { selfSAR, ok := obj.(*authorizationapi.SelfSubjectAccessReview) if !ok { return nil, apierrors.NewBadRequest(fmt.Sprintf("not a SelfSubjectAccessReview: %#v", obj)) } if errs := authorizationvalidation.ValidateSelfSubjectAccessReview(selfSAR); len(errs) > 0 { return nil, apierrors.NewInvalid(authorizationapi.Kind(selfSAR.Kind), "", errs) } userToCheck, exists := api.UserFrom(ctx) if !exists { return nil, apierrors.NewBadRequest("no user present on request") } var authorizationAttributes authorizer.AttributesRecord if selfSAR.Spec.ResourceAttributes != nil { authorizationAttributes = authorizationutil.ResourceAttributesFrom(userToCheck, *selfSAR.Spec.ResourceAttributes) } else { authorizationAttributes = authorizationutil.NonResourceAttributesFrom(userToCheck, *selfSAR.Spec.NonResourceAttributes) } allowed, reason, evaluationErr := r.authorizer.Authorize(authorizationAttributes) selfSAR.Status = authorizationapi.SubjectAccessReviewStatus{ Allowed: allowed, Reason: reason, } if evaluationErr != nil { selfSAR.Status.EvaluationError = evaluationErr.Error() } return selfSAR, nil }
func (r *REST) Create(ctx kapi.Context, obj runtime.Object) (runtime.Object, error) { localSubjectAccessReview, ok := obj.(*authorizationapi.LocalSubjectAccessReview) if !ok { return nil, kapierrors.NewBadRequest(fmt.Sprintf("not a LocaLocalSubjectAccessReview: %#v", obj)) } if errs := authorizationvalidation.ValidateLocalSubjectAccessReview(localSubjectAccessReview); len(errs) > 0 { return nil, kapierrors.NewInvalid(authorizationapi.Kind(localSubjectAccessReview.Kind), "", errs) } namespace := kapi.NamespaceValue(ctx) if len(namespace) == 0 { return nil, kapierrors.NewBadRequest(fmt.Sprintf("namespace is required on this type: %v", namespace)) } if namespace != localSubjectAccessReview.Namespace { return nil, kapierrors.NewBadRequest(fmt.Sprintf("spec.resourceAttributes.namespace must match namespace: %v", namespace)) } authorizationAttributes := authorizationutil.AuthorizationAttributesFrom(localSubjectAccessReview.Spec) allowed, reason, evaluationErr := r.authorizer.Authorize(authorizationAttributes) localSubjectAccessReview.Status = authorizationapi.SubjectAccessReviewStatus{ Allowed: allowed, Reason: reason, } if evaluationErr != nil { localSubjectAccessReview.Status.EvaluationError = evaluationErr.Error() } return localSubjectAccessReview, nil }
func (r *REST) Create(ctx kapi.Context, obj runtime.Object) (runtime.Object, error) { subjectAccessReview, ok := obj.(*authorizationapi.SubjectAccessReview) if !ok { return nil, kapierrors.NewBadRequest(fmt.Sprintf("not a SubjectAccessReview: %#v", obj)) } if errs := authorizationvalidation.ValidateSubjectAccessReview(subjectAccessReview); len(errs) > 0 { return nil, kapierrors.NewInvalid(authorizationapi.Kind(subjectAccessReview.Kind), "", errs) } userToCheck := &user.DefaultInfo{ Name: subjectAccessReview.Spec.User, Groups: subjectAccessReview.Spec.Groups, Extra: convertToUserInfoExtra(subjectAccessReview.Spec.Extra), } var authorizationAttributes authorizer.AttributesRecord if subjectAccessReview.Spec.ResourceAttributes != nil { authorizationAttributes = authorizationutil.ResourceAttributesFrom(userToCheck, *subjectAccessReview.Spec.ResourceAttributes) } else { authorizationAttributes = authorizationutil.NonResourceAttributesFrom(userToCheck, *subjectAccessReview.Spec.NonResourceAttributes) } allowed, reason, evaluationErr := r.authorizer.Authorize(authorizationAttributes) subjectAccessReview.Status = authorizationapi.SubjectAccessReviewStatus{ Allowed: allowed, Reason: reason, } if evaluationErr != nil { subjectAccessReview.Status.EvaluationError = evaluationErr.Error() } return subjectAccessReview, nil }
func (s *REST) Update(ctx kapi.Context, name string, objInfo rest.UpdatedObjectInfo) (runtime.Object, bool, error) { oldObj, err := s.Get(ctx, name) if err != nil { return nil, false, err } obj, err := objInfo.UpdatedObject(ctx, oldObj) if err != nil { return nil, false, err } project, ok := obj.(*api.Project) if !ok { return nil, false, fmt.Errorf("not a project: %#v", obj) } s.updateStrategy.PrepareForUpdate(obj, oldObj) if errs := s.updateStrategy.ValidateUpdate(ctx, obj, oldObj); len(errs) > 0 { return nil, false, kerrors.NewInvalid(projectapi.Kind("Project"), project.Name, errs) } namespace, err := s.client.Update(projectutil.ConvertProject(project)) if err != nil { return nil, false, err } return projectutil.ConvertNamespace(namespace), false, nil }
// BeforeUpdate ensures that common operations for all resources are performed on update. It only returns // errors that can be converted to api.Status. It will invoke update validation with the provided existing // and updated objects. func BeforeUpdate(strategy RESTUpdateStrategy, ctx api.Context, obj, old 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.PrepareForUpdate(obj, old) // Ensure some common fields, like UID, are validated for all resources. errs, err := validateCommonFields(obj, old) if err != nil { return errors.NewInternalError(err) } errs = append(errs, strategy.ValidateUpdate(ctx, obj, old)...) if len(errs) > 0 { return errors.NewInvalid(kind.GroupKind(), objectMeta.Name, errs) } strategy.Canonicalize(obj) return nil }
func (r *ScaleREST) Update(ctx api.Context, obj runtime.Object) (runtime.Object, bool, error) { if obj == nil { return nil, false, errors.NewBadRequest(fmt.Sprintf("nil update passed to Scale")) } scale, ok := obj.(*extensions.Scale) if !ok { return nil, false, errors.NewBadRequest(fmt.Sprintf("wrong object passed to Scale update: %v", obj)) } if errs := extvalidation.ValidateScale(scale); len(errs) > 0 { return nil, false, errors.NewInvalid(extensions.Kind("Scale"), scale.Name, errs) } rs, err := r.registry.GetReplicaSet(ctx, scale.Name) if err != nil { return nil, false, errors.NewNotFound(extensions.Resource("replicasets/scale"), scale.Name) } rs.Spec.Replicas = scale.Spec.Replicas rs.ResourceVersion = scale.ResourceVersion rs, err = r.registry.UpdateReplicaSet(ctx, rs) if err != nil { return nil, false, err } newScale, err := scaleFromReplicaSet(rs) if err != nil { return nil, false, errors.NewBadRequest(fmt.Sprintf("%v", err)) } return newScale, false, err }
func (r *ScaleREST) Update(ctx api.Context, name string, objInfo rest.UpdatedObjectInfo) (runtime.Object, bool, error) { rc, err := r.registry.GetController(ctx, name) if err != nil { return nil, false, errors.NewNotFound(autoscaling.Resource("replicationcontrollers/scale"), name) } oldScale := scaleFromRC(rc) obj, err := objInfo.UpdatedObject(ctx, oldScale) if err != nil { return nil, false, err } if obj == nil { return nil, false, errors.NewBadRequest("nil update passed to Scale") } scale, ok := obj.(*autoscaling.Scale) if !ok { return nil, false, errors.NewBadRequest(fmt.Sprintf("wrong object passed to Scale update: %v", obj)) } if errs := validation.ValidateScale(scale); len(errs) > 0 { return nil, false, errors.NewInvalid(autoscaling.Kind("Scale"), scale.Name, errs) } rc.Spec.Replicas = scale.Spec.Replicas rc.ResourceVersion = scale.ResourceVersion rc, err = r.registry.UpdateController(ctx, rc) if err != nil { return nil, false, err } return scaleFromRC(rc), false, nil }
// Create instantiates a deployment config func (r *REST) Create(ctx kapi.Context, obj runtime.Object) (runtime.Object, error) { req, ok := obj.(*deployapi.DeploymentRequest) if !ok { return nil, errors.NewInternalError(fmt.Errorf("wrong object passed for requesting a new rollout: %#v", obj)) } configObj, err := r.store.Get(ctx, req.Name) if err != nil { return nil, err } config := configObj.(*deployapi.DeploymentConfig) old := config if errs := validation.ValidateRequestForDeploymentConfig(req, config); len(errs) > 0 { return nil, errors.NewInvalid(deployapi.Kind("DeploymentRequest"), req.Name, errs) } // We need to process the deployment config before we can determine if it is possible to trigger // a deployment. if req.Latest { if err := processTriggers(config, r.isn, req.Force); err != nil { return nil, err } } canTrigger, causes, err := canTrigger(config, r.rn, r.decoder, req.Force) if err != nil { return nil, err } // If we cannot trigger then there is nothing to do here. if !canTrigger { return &unversioned.Status{ Message: fmt.Sprintf("deployment config %q cannot be instantiated", config.Name), Code: int32(204), }, nil } glog.V(4).Infof("New deployment for %q caused by %#v", config.Name, causes) config.Status.Details = new(deployapi.DeploymentDetails) config.Status.Details.Causes = causes switch causes[0].Type { case deployapi.DeploymentTriggerOnConfigChange: config.Status.Details.Message = "config change" case deployapi.DeploymentTriggerOnImageChange: config.Status.Details.Message = "image change" case deployapi.DeploymentTriggerManual: config.Status.Details.Message = "manual change" } config.Status.LatestVersion++ userInfo, _ := kapi.UserFrom(ctx) attrs := admission.NewAttributesRecord(config, old, deployapi.Kind("DeploymentConfig").WithVersion(""), config.Namespace, config.Name, deployapi.Resource("DeploymentConfig").WithVersion(""), "", admission.Update, userInfo) if err := r.admit.Admit(attrs); err != nil { return nil, err } updated, _, err := r.store.Update(ctx, config.Name, rest.DefaultUpdatedObjectInfo(config, kapi.Scheme)) return updated, err }
// Create registers a given new PodSecurityPolicyReview instance to r.registry. func (r *REST) Create(ctx kapi.Context, obj runtime.Object) (runtime.Object, error) { pspr, ok := obj.(*securityapi.PodSecurityPolicyReview) if !ok { return nil, kapierrors.NewBadRequest(fmt.Sprintf("not a PodSecurityPolicyReview: %#v", obj)) } if errs := securityvalidation.ValidatePodSecurityPolicyReview(pspr); len(errs) > 0 { return nil, kapierrors.NewInvalid(kapi.Kind("PodSecurityPolicyReview"), "", errs) } ns, ok := kapi.NamespaceFrom(ctx) if !ok { return nil, kapierrors.NewBadRequest("namespace parameter required.") } serviceAccounts, err := getServiceAccounts(pspr.Spec, r.saCache, ns) if err != nil { return nil, kapierrors.NewBadRequest(err.Error()) } if len(serviceAccounts) == 0 { glog.Errorf("No service accounts for namespace %s", ns) return nil, kapierrors.NewBadRequest(fmt.Sprintf("unable to find ServiceAccount for namespace: %s", ns)) } errs := []error{} newStatus := securityapi.PodSecurityPolicyReviewStatus{} for _, sa := range serviceAccounts { userInfo := serviceaccount.UserInfo(ns, sa.Name, "") saConstraints, err := r.sccMatcher.FindApplicableSCCs(userInfo) if err != nil { errs = append(errs, fmt.Errorf("unable to find SecurityContextConstraints for ServiceAccount %s: %v", sa.Name, err)) continue } oscc.DeduplicateSecurityContextConstraints(saConstraints) sort.Sort(oscc.ByPriority(saConstraints)) var namespace *kapi.Namespace for _, constraint := range saConstraints { var ( provider kscc.SecurityContextConstraintsProvider err error ) pspsrs := securityapi.PodSecurityPolicySubjectReviewStatus{} if provider, namespace, err = oscc.CreateProviderFromConstraint(ns, namespace, constraint, r.client); err != nil { errs = append(errs, fmt.Errorf("unable to create provider for service account %s: %v", sa.Name, err)) continue } _, err = podsecuritypolicysubjectreview.FillPodSecurityPolicySubjectReviewStatus(&pspsrs, provider, pspr.Spec.Template.Spec, constraint) if err != nil { glog.Errorf("unable to fill PodSecurityPolicyReviewStatus from constraint %v", err) continue } sapsprs := securityapi.ServiceAccountPodSecurityPolicyReviewStatus{pspsrs, sa.Name} newStatus.AllowedServiceAccounts = append(newStatus.AllowedServiceAccounts, sapsprs) } } if len(errs) > 0 { return nil, kapierrors.NewBadRequest(fmt.Sprintf("%s", kerrors.NewAggregate(errs))) } pspr.Status = newStatus return pspr, nil }
func (c *ErrorReplicationControllers) Update(controller *api.ReplicationController) (*api.ReplicationController, error) { switch { case c.invalid: return nil, kerrors.NewInvalid(api.Kind(controller.Kind), controller.Name, nil) case c.conflict: return nil, kerrors.NewConflict(api.Resource(controller.Kind), controller.Name, nil) } return nil, errors.New("Replication controller update failure") }
func (c *ErrorDeployments) Update(deployment *extensions.Deployment) (*extensions.Deployment, error) { switch { case c.invalid: return nil, kerrors.NewInvalid(api.Kind(deployment.Kind), deployment.Name, nil) case c.conflict: return nil, kerrors.NewConflict(api.Resource(deployment.Kind), deployment.Name, nil) } return nil, errors.New("deployment update failure") }