github.com/timstclair/heapster@v0.20.0-alpha1/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/rest/update.go (about) 1 /* 2 Copyright 2014 The Kubernetes Authors All rights reserved. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package rest 18 19 import ( 20 "k8s.io/kubernetes/pkg/api" 21 "k8s.io/kubernetes/pkg/api/errors" 22 "k8s.io/kubernetes/pkg/api/validation" 23 "k8s.io/kubernetes/pkg/runtime" 24 utilvalidation "k8s.io/kubernetes/pkg/util/validation" 25 ) 26 27 // RESTUpdateStrategy defines the minimum validation, accepted input, and 28 // name generation behavior to update an object that follows Kubernetes 29 // API conventions. A resource may have many UpdateStrategies, depending on 30 // the call pattern in use. 31 type RESTUpdateStrategy interface { 32 runtime.ObjectTyper 33 // NamespaceScoped returns true if the object must be within a namespace. 34 NamespaceScoped() bool 35 // AllowCreateOnUpdate returns true if the object can be created by a PUT. 36 AllowCreateOnUpdate() bool 37 // PrepareForUpdate is invoked on update before validation to normalize 38 // the object. For example: remove fields that are not to be persisted, 39 // sort order-insensitive list fields, etc. This should not remove fields 40 // whose presence would be considered a validation error. 41 PrepareForUpdate(obj, old runtime.Object) 42 // ValidateUpdate is invoked after default fields in the object have been 43 // filled in before the object is persisted. This method should not mutate 44 // the object. 45 ValidateUpdate(ctx api.Context, obj, old runtime.Object) utilvalidation.ErrorList 46 // Canonicalize is invoked after validation has succeeded but before the 47 // object has been persisted. This method may mutate the object. 48 Canonicalize(obj runtime.Object) 49 // AllowUnconditionalUpdate returns true if the object can be updated 50 // unconditionally (irrespective of the latest resource version), when 51 // there is no resource version specified in the object. 52 AllowUnconditionalUpdate() bool 53 } 54 55 // TODO: add other common fields that require global validation. 56 func validateCommonFields(obj, old runtime.Object) utilvalidation.ErrorList { 57 allErrs := utilvalidation.ErrorList{} 58 objectMeta, err := api.ObjectMetaFor(obj) 59 if err != nil { 60 return append(allErrs, utilvalidation.NewInternalError("metadata", err)) 61 } 62 oldObjectMeta, err := api.ObjectMetaFor(old) 63 if err != nil { 64 return append(allErrs, utilvalidation.NewInternalError("metadata", err)) 65 } 66 allErrs = append(allErrs, validation.ValidateObjectMetaUpdate(objectMeta, oldObjectMeta)...) 67 68 return allErrs 69 } 70 71 // BeforeUpdate ensures that common operations for all resources are performed on update. It only returns 72 // errors that can be converted to api.Status. It will invoke update validation with the provided existing 73 // and updated objects. 74 func BeforeUpdate(strategy RESTUpdateStrategy, ctx api.Context, obj, old runtime.Object) error { 75 objectMeta, kind, kerr := objectMetaAndKind(strategy, obj) 76 if kerr != nil { 77 return kerr 78 } 79 if strategy.NamespaceScoped() { 80 if !api.ValidNamespace(ctx, objectMeta) { 81 return errors.NewBadRequest("the namespace of the provided object does not match the namespace sent on the request") 82 } 83 } else { 84 objectMeta.Namespace = api.NamespaceNone 85 } 86 87 strategy.PrepareForUpdate(obj, old) 88 89 // Ensure some common fields, like UID, are validated for all resources. 90 errs := validateCommonFields(obj, old) 91 92 errs = append(errs, strategy.ValidateUpdate(ctx, obj, old)...) 93 if len(errs) > 0 { 94 return errors.NewInvalid(kind, objectMeta.Name, errs) 95 } 96 97 strategy.Canonicalize(obj) 98 99 return nil 100 }