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  }