update CRD strategy for status updates

1. Clear the status of the CRD and set the Generation before creation.
2. While updating the CRD:
    - ignore changes on status.
    - increase Generation if spec changes.
3. Don't update objectmeta when status is updated.
    - however, update finalizers. Without this, deletion will timeout.
This commit is contained in:
Nikhita Raghunath 2017-08-16 17:54:48 +05:30
parent baa6b2ff20
commit 5c354615e0
4 changed files with 40 additions and 15 deletions

View File

@ -24,13 +24,13 @@ import (
genericregistry "k8s.io/apiserver/pkg/registry/generic/registry"
)
// rest implements a RESTStorage for API services against etcd
// REST implements a RESTStorage for API services against etcd
type REST struct {
*genericregistry.Store
}
// NewREST returns a RESTStorage object that will work against API services.
func NewREST(resource schema.GroupResource, listKind schema.GroupVersionKind, copier runtime.ObjectCopier, strategy CustomResourceDefinitionStorageStrategy, optsGetter generic.RESTOptionsGetter) *REST {
func NewREST(resource schema.GroupResource, listKind schema.GroupVersionKind, copier runtime.ObjectCopier, strategy customResourceDefinitionStorageStrategy, optsGetter generic.RESTOptionsGetter) *REST {
store := &genericregistry.Store{
Copier: copier,
NewFunc: func() runtime.Object { return &unstructured.Unstructured{} },

View File

@ -32,7 +32,7 @@ import (
"k8s.io/apiserver/pkg/storage/names"
)
type CustomResourceDefinitionStorageStrategy struct {
type customResourceDefinitionStorageStrategy struct {
runtime.ObjectTyper
names.NameGenerator
@ -40,8 +40,8 @@ type CustomResourceDefinitionStorageStrategy struct {
validator customResourceValidator
}
func NewStrategy(typer runtime.ObjectTyper, namespaceScoped bool, kind schema.GroupVersionKind) CustomResourceDefinitionStorageStrategy {
return CustomResourceDefinitionStorageStrategy{
func NewStrategy(typer runtime.ObjectTyper, namespaceScoped bool, kind schema.GroupVersionKind) customResourceDefinitionStorageStrategy {
return customResourceDefinitionStorageStrategy{
ObjectTyper: typer,
NameGenerator: names.SimpleNameGenerator,
namespaceScoped: namespaceScoped,
@ -52,36 +52,36 @@ func NewStrategy(typer runtime.ObjectTyper, namespaceScoped bool, kind schema.Gr
}
}
func (a CustomResourceDefinitionStorageStrategy) NamespaceScoped() bool {
func (a customResourceDefinitionStorageStrategy) NamespaceScoped() bool {
return a.namespaceScoped
}
func (CustomResourceDefinitionStorageStrategy) PrepareForCreate(ctx genericapirequest.Context, obj runtime.Object) {
func (customResourceDefinitionStorageStrategy) PrepareForCreate(ctx genericapirequest.Context, obj runtime.Object) {
}
func (CustomResourceDefinitionStorageStrategy) PrepareForUpdate(ctx genericapirequest.Context, obj, old runtime.Object) {
func (customResourceDefinitionStorageStrategy) PrepareForUpdate(ctx genericapirequest.Context, obj, old runtime.Object) {
}
func (a CustomResourceDefinitionStorageStrategy) Validate(ctx genericapirequest.Context, obj runtime.Object) field.ErrorList {
func (a customResourceDefinitionStorageStrategy) Validate(ctx genericapirequest.Context, obj runtime.Object) field.ErrorList {
return a.validator.Validate(ctx, obj)
}
func (CustomResourceDefinitionStorageStrategy) AllowCreateOnUpdate() bool {
func (customResourceDefinitionStorageStrategy) AllowCreateOnUpdate() bool {
return false
}
func (CustomResourceDefinitionStorageStrategy) AllowUnconditionalUpdate() bool {
func (customResourceDefinitionStorageStrategy) AllowUnconditionalUpdate() bool {
return false
}
func (CustomResourceDefinitionStorageStrategy) Canonicalize(obj runtime.Object) {
func (customResourceDefinitionStorageStrategy) Canonicalize(obj runtime.Object) {
}
func (a CustomResourceDefinitionStorageStrategy) ValidateUpdate(ctx genericapirequest.Context, obj, old runtime.Object) field.ErrorList {
func (a customResourceDefinitionStorageStrategy) ValidateUpdate(ctx genericapirequest.Context, obj, old runtime.Object) field.ErrorList {
return a.validator.ValidateUpdate(ctx, obj, old)
}
func (a CustomResourceDefinitionStorageStrategy) GetAttrs(obj runtime.Object) (labels.Set, fields.Set, bool, error) {
func (a customResourceDefinitionStorageStrategy) GetAttrs(obj runtime.Object) (labels.Set, fields.Set, bool, error) {
accessor, err := meta.Accessor(obj)
if err != nil {
return nil, nil, false, err
@ -102,7 +102,7 @@ func objectMetaFieldsSet(objectMeta metav1.Object, namespaceScoped bool) fields.
}
}
func (a CustomResourceDefinitionStorageStrategy) MatchCustomResourceDefinitionStorage(label labels.Selector, field fields.Selector) storage.SelectionPredicate {
func (a customResourceDefinitionStorageStrategy) MatchCustomResourceDefinitionStorage(label labels.Selector, field fields.Selector) storage.SelectionPredicate {
return storage.SelectionPredicate{
Label: label,
Field: field,

View File

@ -14,6 +14,7 @@ go_library(
deps = [
"//vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions:go_default_library",
"//vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/validation:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/equality:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/fields:go_default_library",

View File

@ -19,6 +19,7 @@ package customresourcedefinition
import (
"fmt"
apiequality "k8s.io/apimachinery/pkg/api/equality"
"k8s.io/apimachinery/pkg/fields"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/runtime"
@ -46,9 +47,27 @@ func (strategy) NamespaceScoped() bool {
}
func (strategy) PrepareForCreate(ctx genericapirequest.Context, obj runtime.Object) {
crd := obj.(*apiextensions.CustomResourceDefinition)
crd.Status = apiextensions.CustomResourceDefinitionStatus{}
crd.Generation = 1
}
func (strategy) PrepareForUpdate(ctx genericapirequest.Context, obj, old runtime.Object) {
newCRD := obj.(*apiextensions.CustomResourceDefinition)
oldCRD := old.(*apiextensions.CustomResourceDefinition)
newCRD.Status = oldCRD.Status
// Any changes to the spec increment the generation number, any changes to the
// status should reflect the generation number of the corresponding object. We push
// the burden of managing the status onto the clients because we can't (in general)
// know here what version of spec the writer of the status has seen. It may seem like
// we can at first -- since obj contains spec -- but in the future we will probably make
// status its own object, and even if we don't, writes may be the result of a
// read-update-write loop, so the contents of spec may not actually be the spec that
// the controller has *seen*.
if !apiequality.Semantic.DeepEqual(oldCRD.Spec, newCRD.Spec) {
newCRD.Generation = oldCRD.Generation + 1
}
}
func (strategy) Validate(ctx genericapirequest.Context, obj runtime.Object) field.ErrorList {
@ -87,9 +106,14 @@ func (statusStrategy) PrepareForUpdate(ctx genericapirequest.Context, obj, old r
newObj := obj.(*apiextensions.CustomResourceDefinition)
oldObj := old.(*apiextensions.CustomResourceDefinition)
newObj.Spec = oldObj.Spec
// Status updates are for only for updating status, not objectmeta.
// TODO: Update after ResetObjectMetaForStatus is added to meta/v1.
newObj.Labels = oldObj.Labels
newObj.Annotations = oldObj.Annotations
newObj.OwnerReferences = oldObj.OwnerReferences
newObj.Generation = oldObj.Generation
newObj.SelfLink = oldObj.SelfLink
}
func (statusStrategy) AllowCreateOnUpdate() bool {