diff --git a/pkg/registry/servicecatalog/serviceclass/storage.go b/pkg/registry/servicecatalog/clusterserviceclass/storage.go similarity index 81% rename from pkg/registry/servicecatalog/serviceclass/storage.go rename to pkg/registry/servicecatalog/clusterserviceclass/storage.go index 489c58c2a6f0..d718f4a63f83 100644 --- a/pkg/registry/servicecatalog/serviceclass/storage.go +++ b/pkg/registry/servicecatalog/clusterserviceclass/storage.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package serviceclass +package clusterserviceclass import ( "errors" @@ -38,8 +38,8 @@ var ( errNotAClusterServiceClass = errors.New("not a ClusterServiceClass") ) -// NewSingular returns a new shell of a service class, according to the given namespace and -// name +// NewSingular returns a new shell of a cluster service class, according to the +// given namespace and name. func NewSingular(ns, name string) runtime.Object { return &servicecatalog.ClusterServiceClass{ TypeMeta: metav1.TypeMeta{ @@ -52,12 +52,12 @@ func NewSingular(ns, name string) runtime.Object { } } -// EmptyObject returns an empty service class +// EmptyObject returns an empty cluster service class. func EmptyObject() runtime.Object { return &servicecatalog.ClusterServiceClass{} } -// NewList returns a new shell of a service class list +// NewList returns a new shell of a cluster service class list. func NewList() runtime.Object { return &servicecatalog.ClusterServiceClassList{ TypeMeta: metav1.TypeMeta{ @@ -67,7 +67,8 @@ func NewList() runtime.Object { } } -// CheckObject returns a non-nil error if obj is not a service class object +// CheckObject returns a non-nil error if obj is not a cluster service class +// object. func CheckObject(obj runtime.Object) error { _, ok := obj.(*servicecatalog.ClusterServiceClass) if !ok { @@ -86,19 +87,20 @@ func Match(label labels.Selector, field fields.Selector) storage.SelectionPredic } } -// toSelectableFields returns a field set that represents the object for matching purposes. -func toSelectableFields(serviceClass *servicecatalog.ClusterServiceClass) fields.Set { +// toSelectableFields returns a field set that represents the object for +// matching purposes. +func toSelectableFields(clusterServiceClass *servicecatalog.ClusterServiceClass) fields.Set { // The purpose of allocation with a given number of elements is to reduce // amount of allocations needed to create the fields.Set. If you add any // field here or the number of object-meta related fields changes, this should // be adjusted. // You also need to modify // pkg/apis/servicecatalog/v1beta1/conversion[_test].go - scSpecificFieldsSet := make(fields.Set, 3) - scSpecificFieldsSet["spec.clusterServiceBrokerName"] = serviceClass.Spec.ClusterServiceBrokerName - scSpecificFieldsSet["spec.externalName"] = serviceClass.Spec.ExternalName - scSpecificFieldsSet["spec.externalID"] = serviceClass.Spec.ExternalID - return generic.AddObjectMetaFieldsSet(scSpecificFieldsSet, &serviceClass.ObjectMeta, true) + cscSpecificFieldsSet := make(fields.Set, 3) + cscSpecificFieldsSet["spec.clusterServiceBrokerName"] = clusterServiceClass.Spec.ClusterServiceBrokerName + cscSpecificFieldsSet["spec.externalName"] = clusterServiceClass.Spec.ExternalName + cscSpecificFieldsSet["spec.externalID"] = clusterServiceClass.Spec.ExternalID + return generic.AddObjectMetaFieldsSet(cscSpecificFieldsSet, &clusterServiceClass.ObjectMeta, true) } // GetAttrs returns labels and fields of a given object for filtering purposes. @@ -110,15 +112,15 @@ func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, bool, error) { return labels.Set(serviceclass.ObjectMeta.Labels), toSelectableFields(serviceclass), serviceclass.Initializers != nil, nil } -// NewStorage creates a new rest.Storage responsible for accessing ClusterServiceClass -// resources +// NewStorage creates a new rest.Storage responsible for accessing +// ClusterServiceClass resources. func NewStorage(opts server.Options) (rest.Storage, rest.Storage) { prefix := "/" + opts.ResourcePrefix() storageInterface, dFunc := opts.GetStorage( &servicecatalog.ClusterServiceClass{}, prefix, - serviceClassRESTStrategies, + clusterServiceClassRESTStrategies, NewList, nil, storage.NoTriggerPublisher, @@ -139,9 +141,9 @@ func NewStorage(opts server.Options) (rest.Storage, rest.Storage) { // DefaultQualifiedResource should always be plural DefaultQualifiedResource: servicecatalog.Resource("clusterserviceclasses"), - CreateStrategy: serviceClassRESTStrategies, - UpdateStrategy: serviceClassRESTStrategies, - DeleteStrategy: serviceClassRESTStrategies, + CreateStrategy: clusterServiceClassRESTStrategies, + UpdateStrategy: clusterServiceClassRESTStrategies, + DeleteStrategy: clusterServiceClassRESTStrategies, Storage: storageInterface, DestroyFunc: dFunc, } @@ -152,7 +154,7 @@ func NewStorage(opts server.Options) (rest.Storage, rest.Storage) { } statusStore := store - statusStore.UpdateStrategy = serviceClassStatusUpdateStrategy + statusStore.UpdateStrategy = clusterServiceClassStatusUpdateStrategy return &store, &StatusREST{&statusStore} } @@ -164,7 +166,7 @@ type StatusREST struct { store *registry.Store } -// New returns a new ServiceClass +// New returns a new ClusterServiceClass. func (r *StatusREST) New() runtime.Object { return &servicecatalog.ClusterServiceClass{} } diff --git a/pkg/registry/servicecatalog/serviceclass/storage_test.go b/pkg/registry/servicecatalog/clusterserviceclass/storage_test.go similarity index 96% rename from pkg/registry/servicecatalog/serviceclass/storage_test.go rename to pkg/registry/servicecatalog/clusterserviceclass/storage_test.go index 3213621cdba6..7480224d7ddf 100644 --- a/pkg/registry/servicecatalog/serviceclass/storage_test.go +++ b/pkg/registry/servicecatalog/clusterserviceclass/storage_test.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package serviceclass +package clusterserviceclass import ( "testing" diff --git a/pkg/registry/servicecatalog/clusterserviceclass/strategy.go b/pkg/registry/servicecatalog/clusterserviceclass/strategy.go new file mode 100644 index 000000000000..aff995f4d69a --- /dev/null +++ b/pkg/registry/servicecatalog/clusterserviceclass/strategy.go @@ -0,0 +1,153 @@ +/* +Copyright 2017 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package clusterserviceclass + +// this was copied from where else and edited to fit our objects + +import ( + "github.com/kubernetes-incubator/service-catalog/pkg/api" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/util/validation/field" + genericapirequest "k8s.io/apiserver/pkg/endpoints/request" + "k8s.io/apiserver/pkg/registry/rest" + "k8s.io/apiserver/pkg/storage/names" + + "github.com/golang/glog" + sc "github.com/kubernetes-incubator/service-catalog/pkg/apis/servicecatalog" + scv "github.com/kubernetes-incubator/service-catalog/pkg/apis/servicecatalog/validation" +) + +// NewScopeStrategy returns a new NamespaceScopedStrategy for cluster service +// classes. +func NewScopeStrategy() rest.NamespaceScopedStrategy { + return clusterServiceClassRESTStrategies +} + +// clusterServiceClassRESTStrategy implements interfaces RESTCreateStrategy, +// RESTUpdateStrategy, RESTDeleteStrategy, NamespaceScopedStrategy. +type clusterServiceClassRESTStrategy struct { + runtime.ObjectTyper // inherit ObjectKinds method + names.NameGenerator // GenerateName method for CreateStrategy +} + +// clusterServiceClassStatusRESTStrategy implements interface +// RESTUpdateStrategy. This implementation validates updates to +// clusterServiceClass.Status updates only and disallows any modifications to +// the clusterServiceClass.Spec. +type clusterServiceClassStatusRESTStrategy struct { + clusterServiceClassRESTStrategy +} + +var ( + clusterServiceClassRESTStrategies = clusterServiceClassRESTStrategy{ + // embeds to pull in existing code behavior from upstream + + ObjectTyper: api.Scheme, + // use the generator from upstream k8s, or implement method + // `GenerateName(base string) string` + NameGenerator: names.SimpleNameGenerator, + } + _ rest.RESTCreateStrategy = clusterServiceClassRESTStrategies + _ rest.RESTUpdateStrategy = clusterServiceClassRESTStrategies + _ rest.RESTDeleteStrategy = clusterServiceClassRESTStrategies + + clusterServiceClassStatusUpdateStrategy = clusterServiceClassStatusRESTStrategy{ + clusterServiceClassRESTStrategies, + } + _ rest.RESTUpdateStrategy = clusterServiceClassStatusUpdateStrategy +) + +// Canonicalize does not transform a ClusterServiceClass. +func (clusterServiceClassRESTStrategy) Canonicalize(obj runtime.Object) { + _, ok := obj.(*sc.ClusterServiceClass) + if !ok { + glog.Fatal("received a non-clusterserviceclass object to create") + } +} + +// NamespaceScoped returns false as ClusterServiceClass are not scoped to a +// namespace. +func (clusterServiceClassRESTStrategy) NamespaceScoped() bool { + return false +} + +// PrepareForCreate receives the incoming ClusterServiceClass. +func (clusterServiceClassRESTStrategy) PrepareForCreate(ctx genericapirequest.Context, obj runtime.Object) { + clusterServiceClass, ok := obj.(*sc.ClusterServiceClass) + if !ok { + glog.Fatal("received a non-clusterserviceclass object to create") + } + clusterServiceClass.Status = sc.ClusterServiceClassStatus{} +} + +func (clusterServiceClassRESTStrategy) Validate(ctx genericapirequest.Context, obj runtime.Object) field.ErrorList { + return scv.ValidateClusterServiceClass(obj.(*sc.ClusterServiceClass)) +} + +func (clusterServiceClassRESTStrategy) AllowCreateOnUpdate() bool { + return false +} + +func (clusterServiceClassRESTStrategy) AllowUnconditionalUpdate() bool { + return false +} + +func (clusterServiceClassRESTStrategy) PrepareForUpdate(ctx genericapirequest.Context, new, old runtime.Object) { + newServiceClass, ok := new.(*sc.ClusterServiceClass) + if !ok { + glog.Fatal("received a non-clusterserviceclass object to update to") + } + oldServiceClass, ok := old.(*sc.ClusterServiceClass) + if !ok { + glog.Fatal("received a non-clusterserviceclass object to update from") + } + + // Update should not change the status + newServiceClass.Status = oldServiceClass.Status + + newServiceClass.Spec.ClusterServiceBrokerName = oldServiceClass.Spec.ClusterServiceBrokerName +} + +func (clusterServiceClassRESTStrategy) ValidateUpdate(ctx genericapirequest.Context, new, old runtime.Object) field.ErrorList { + newServiceclass, ok := new.(*sc.ClusterServiceClass) + if !ok { + glog.Fatal("received a non-clusterserviceclass object to validate to") + } + oldServiceclass, ok := old.(*sc.ClusterServiceClass) + if !ok { + glog.Fatal("received a non-clusterserviceclass object to validate from") + } + + return scv.ValidateClusterServiceClassUpdate(newServiceclass, oldServiceclass) +} + +func (clusterServiceClassStatusRESTStrategy) PrepareForUpdate(ctx genericapirequest.Context, new, old runtime.Object) { + newServiceClass, ok := new.(*sc.ClusterServiceClass) + if !ok { + glog.Fatal("received a non-clusterserviceClass object to update to") + } + oldServiceClass, ok := old.(*sc.ClusterServiceClass) + if !ok { + glog.Fatal("received a non-clusterserviceClass object to update from") + } + // Status changes are not allowed to update spec + newServiceClass.Spec = oldServiceClass.Spec +} + +func (clusterServiceClassStatusRESTStrategy) ValidateUpdate(ctx genericapirequest.Context, new, old runtime.Object) field.ErrorList { + return field.ErrorList{} +} diff --git a/pkg/registry/servicecatalog/rest/storage_servicecatalog.go b/pkg/registry/servicecatalog/rest/storage_servicecatalog.go index 82a4ee0a75b6..381f2a4681e8 100644 --- a/pkg/registry/servicecatalog/rest/storage_servicecatalog.go +++ b/pkg/registry/servicecatalog/rest/storage_servicecatalog.go @@ -22,9 +22,9 @@ import ( servicecatalogv1beta1 "github.com/kubernetes-incubator/service-catalog/pkg/apis/servicecatalog/v1beta1" "github.com/kubernetes-incubator/service-catalog/pkg/registry/servicecatalog/binding" "github.com/kubernetes-incubator/service-catalog/pkg/registry/servicecatalog/broker" + "github.com/kubernetes-incubator/service-catalog/pkg/registry/servicecatalog/clusterserviceclass" "github.com/kubernetes-incubator/service-catalog/pkg/registry/servicecatalog/instance" "github.com/kubernetes-incubator/service-catalog/pkg/registry/servicecatalog/server" - "github.com/kubernetes-incubator/service-catalog/pkg/registry/servicecatalog/serviceclass" "github.com/kubernetes-incubator/service-catalog/pkg/registry/servicecatalog/serviceplan" "github.com/kubernetes-incubator/service-catalog/pkg/storage/etcd" "k8s.io/apiserver/pkg/registry/generic" @@ -86,18 +86,18 @@ func (p StorageProvider) v1beta1Storage( p.StorageType, ) - serviceClassRESTOptions, err := restOptionsGetter.GetRESTOptions(servicecatalog.Resource("clusterserviceclasses")) + clusterServiceClassRESTOptions, err := restOptionsGetter.GetRESTOptions(servicecatalog.Resource("clusterserviceclasses")) if err != nil { return nil, err } - serviceClassOpts := server.NewOptions( + clusterServiceClassOpts := server.NewOptions( etcd.Options{ - RESTOptions: serviceClassRESTOptions, + RESTOptions: clusterServiceClassRESTOptions, Capacity: 1000, - ObjectType: serviceclass.EmptyObject(), - ScopeStrategy: serviceclass.NewScopeStrategy(), - NewListFunc: serviceclass.NewList, - GetAttrsFunc: serviceclass.GetAttrs, + ObjectType: clusterserviceclass.EmptyObject(), + ScopeStrategy: clusterserviceclass.NewScopeStrategy(), + NewListFunc: clusterserviceclass.NewList, + GetAttrsFunc: clusterserviceclass.GetAttrs, Trigger: storage.NoTriggerPublisher, }, p.StorageType, @@ -155,7 +155,7 @@ func (p StorageProvider) v1beta1Storage( ) brokerStorage, brokerStatusStorage := broker.NewStorage(*brokerOpts) - serviceClassStorage, serviceClassStatusStorage := serviceclass.NewStorage(*serviceClassOpts) + clusterServiceClassStorage, clusterServiceClassStatusStorage := clusterserviceclass.NewStorage(*clusterServiceClassOpts) servicePlanStorage, servicePlanStatusStorage := serviceplan.NewStorage(*servicePlanOpts) instanceStorage, instanceStatusStorage, instanceReferencesStorage := instance.NewStorage(*instanceOpts) bindingStorage, bindingStatusStorage, err := binding.NewStorage(*bindingsOpts) @@ -166,8 +166,8 @@ func (p StorageProvider) v1beta1Storage( return map[string]rest.Storage{ "clusterservicebrokers": brokerStorage, "clusterservicebrokers/status": brokerStatusStorage, - "clusterserviceclasses": serviceClassStorage, - "clusterserviceclasses/status": serviceClassStatusStorage, + "clusterserviceclasses": clusterServiceClassStorage, + "clusterserviceclasses/status": clusterServiceClassStatusStorage, "clusterserviceplans": servicePlanStorage, "clusterserviceplans/status": servicePlanStatusStorage, "serviceinstances": instanceStorage, diff --git a/pkg/registry/servicecatalog/serviceclass/strategy.go b/pkg/registry/servicecatalog/serviceclass/strategy.go deleted file mode 100644 index fa0f14453385..000000000000 --- a/pkg/registry/servicecatalog/serviceclass/strategy.go +++ /dev/null @@ -1,160 +0,0 @@ -/* -Copyright 2017 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package serviceclass - -// this was copied from where else and edited to fit our objects - -import ( - "github.com/kubernetes-incubator/service-catalog/pkg/api" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/util/validation/field" - genericapirequest "k8s.io/apiserver/pkg/endpoints/request" - "k8s.io/apiserver/pkg/registry/rest" - "k8s.io/apiserver/pkg/storage/names" - - "github.com/golang/glog" - sc "github.com/kubernetes-incubator/service-catalog/pkg/apis/servicecatalog" - scv "github.com/kubernetes-incubator/service-catalog/pkg/apis/servicecatalog/validation" -) - -// NewScopeStrategy returns a new NamespaceScopedStrategy for service classes -func NewScopeStrategy() rest.NamespaceScopedStrategy { - return serviceClassRESTStrategies -} - -// implements interfaces RESTCreateStrategy, RESTUpdateStrategy, RESTDeleteStrategy, -// NamespaceScopedStrategy -type serviceClassRESTStrategy struct { - runtime.ObjectTyper // inherit ObjectKinds method - names.NameGenerator // GenerateName method for CreateStrategy -} - -// implements interface RESTUpdateStrategy. This implementation validates updates to -// serviceClass.Status updates only and disallows any modifications to the serviceClass.Spec. -type serviceClassStatusRESTStrategy struct { - serviceClassRESTStrategy -} - -var ( - serviceClassRESTStrategies = serviceClassRESTStrategy{ - // embeds to pull in existing code behavior from upstream - - ObjectTyper: api.Scheme, - // use the generator from upstream k8s, or implement method - // `GenerateName(base string) string` - NameGenerator: names.SimpleNameGenerator, - } - _ rest.RESTCreateStrategy = serviceClassRESTStrategies - _ rest.RESTUpdateStrategy = serviceClassRESTStrategies - _ rest.RESTDeleteStrategy = serviceClassRESTStrategies - - serviceClassStatusUpdateStrategy = serviceClassStatusRESTStrategy{ - serviceClassRESTStrategies, - } - _ rest.RESTUpdateStrategy = serviceClassStatusUpdateStrategy -) - -// Canonicalize does not transform a serviceclass. -func (serviceClassRESTStrategy) Canonicalize(obj runtime.Object) { - _, ok := obj.(*sc.ClusterServiceClass) - if !ok { - glog.Fatal("received a non-serviceclass object to create") - } -} - -// NamespaceScoped returns false as serviceclasss are not scoped to a namespace. -func (serviceClassRESTStrategy) NamespaceScoped() bool { - return false -} - -// PrepareForCreate receives the incoming Serviceclass. -func (serviceClassRESTStrategy) PrepareForCreate(ctx genericapirequest.Context, obj runtime.Object) { - serviceClass, ok := obj.(*sc.ClusterServiceClass) - if !ok { - glog.Fatal("received a non-serviceclass object to create") - } - serviceClass.Status = sc.ClusterServiceClassStatus{} -} - -func (serviceClassRESTStrategy) Validate(ctx genericapirequest.Context, obj runtime.Object) field.ErrorList { - return scv.ValidateClusterServiceClass(obj.(*sc.ClusterServiceClass)) -} - -func (serviceClassRESTStrategy) AllowCreateOnUpdate() bool { - return false -} - -func (serviceClassRESTStrategy) AllowUnconditionalUpdate() bool { - return false -} - -func (serviceClassRESTStrategy) PrepareForUpdate(ctx genericapirequest.Context, new, old runtime.Object) { - newServiceClass, ok := new.(*sc.ClusterServiceClass) - if !ok { - glog.Fatal("received a non-serviceclass object to update to") - } - oldServiceClass, ok := old.(*sc.ClusterServiceClass) - if !ok { - glog.Fatal("received a non-serviceclass object to update from") - } - - // Update should not change the status - newServiceClass.Status = oldServiceClass.Status - - newServiceClass.Spec.ClusterServiceBrokerName = oldServiceClass.Spec.ClusterServiceBrokerName -} - -func (serviceClassRESTStrategy) ValidateUpdate(ctx genericapirequest.Context, new, old runtime.Object) field.ErrorList { - newServiceclass, ok := new.(*sc.ClusterServiceClass) - if !ok { - glog.Fatal("received a non-serviceclass object to validate to") - } - oldServiceclass, ok := old.(*sc.ClusterServiceClass) - if !ok { - glog.Fatal("received a non-serviceclass object to validate from") - } - - return scv.ValidateClusterServiceClassUpdate(newServiceclass, oldServiceclass) -} - -func (serviceClassStatusRESTStrategy) PrepareForUpdate(ctx genericapirequest.Context, new, old runtime.Object) { - newServiceClass, ok := new.(*sc.ClusterServiceClass) - if !ok { - glog.Fatal("received a non-serviceClass object to update to") - } - oldServiceClass, ok := old.(*sc.ClusterServiceClass) - if !ok { - glog.Fatal("received a non-serviceClass object to update from") - } - // Status changes are not allowed to update spec - newServiceClass.Spec = oldServiceClass.Spec -} - -func (serviceClassStatusRESTStrategy) ValidateUpdate(ctx genericapirequest.Context, new, old runtime.Object) field.ErrorList { - // newServiceClass, ok := new.(*sc.ServiceClass) - // if !ok { - // glog.Fatal("received a non-serviceClass object to validate to") - // } - // oldServiceClass, ok := old.(*sc.ServiceClass) - // if !ok { - // glog.Fatal("received a non-serviceClass object to validate from") - // } - - // return scv.ValidateServiceClassStatusUpdate(newServiceClass, oldServiceClass) - - return field.ErrorList{} -}