diff --git a/pkg/apis/servicecatalog/types.go b/pkg/apis/servicecatalog/types.go index 42c93537ff8..990b9f89a89 100644 --- a/pkg/apis/servicecatalog/types.go +++ b/pkg/apis/servicecatalog/types.go @@ -150,6 +150,7 @@ type CommonServiceBrokerSpec struct { // name - the value set to [Cluster]ServicePlan.Name // spec.externalName - the value set to [Cluster]ServicePlan.Spec.ExternalName // spec.externalID - the value set to [Cluster]ServicePlan.Spec.ExternalID +// spec.free - the value set to [Cluster]ServicePlan.Spec.Free // spec.serviceClassName - the value set to ServicePlan.Spec.ServiceClassRef.Name // spec.clusterServiceClass.name - the value set to ClusterServicePlan.Spec.ClusterServiceClassRef.Name type CatalogRestrictions struct { diff --git a/pkg/apis/servicecatalog/v1beta1/filter.go b/pkg/apis/servicecatalog/v1beta1/filter.go index bdbec158e32..16aa52bba18 100644 --- a/pkg/apis/servicecatalog/v1beta1/filter.go +++ b/pkg/apis/servicecatalog/v1beta1/filter.go @@ -17,6 +17,8 @@ limitations under the License. package v1beta1 import ( + "strconv" + "github.com/kubernetes-incubator/service-catalog/pkg/filter" "k8s.io/apimachinery/pkg/labels" ) @@ -50,6 +52,7 @@ func ConvertServicePlanToProperties(servicePlan *ServicePlan) filter.Properties FilterSpecExternalName: servicePlan.Spec.ExternalName, FilterSpecExternalID: servicePlan.Spec.ExternalID, FilterSpecServiceClassName: servicePlan.Spec.ServiceClassRef.Name, + FilterSpecFree: strconv.FormatBool(servicePlan.Spec.Free), } } @@ -79,5 +82,6 @@ func ConvertClusterServicePlanToProperties(servicePlan *ClusterServicePlan) filt FilterSpecExternalName: servicePlan.Spec.ExternalName, FilterSpecExternalID: servicePlan.Spec.ExternalID, FilterSpecClusterServiceClassName: servicePlan.Spec.ClusterServiceClassRef.Name, + FilterSpecFree: strconv.FormatBool(servicePlan.Spec.Free), } } diff --git a/pkg/apis/servicecatalog/v1beta1/filter_test.go b/pkg/apis/servicecatalog/v1beta1/filter_test.go index 0aea3ad916d..4fffab767f4 100644 --- a/pkg/apis/servicecatalog/v1beta1/filter_test.go +++ b/pkg/apis/servicecatalog/v1beta1/filter_test.go @@ -83,13 +83,14 @@ func TestConvertServicePlanToProperties(t *testing.T) { CommonServicePlanSpec: CommonServicePlanSpec{ ExternalName: "external-plan-name", ExternalID: "external-id", + Free: true, }, ServiceClassRef: LocalObjectReference{ Name: "service-class-name", }, }, }, - json: `{"name":"service-plan","spec.externalID":"external-id","spec.externalName":"external-plan-name","spec.serviceClass.name":"service-class-name"}`, + json: `{"name":"service-plan","spec.externalID":"external-id","spec.externalName":"external-plan-name","spec.free":"true","spec.serviceClass.name":"service-class-name"}`, }, } for _, tc := range cases { @@ -170,13 +171,14 @@ func TestConvertClusterServicePlanToProperties(t *testing.T) { CommonServicePlanSpec: CommonServicePlanSpec{ ExternalName: "external-plan-name", ExternalID: "external-id", + Free: true, }, ClusterServiceClassRef: ClusterObjectReference{ Name: "cluster-service-class-name", }, }, }, - json: `{"name":"service-plan","spec.clusterServiceClass.name":"cluster-service-class-name","spec.externalID":"external-id","spec.externalName":"external-plan-name"}`, + json: `{"name":"service-plan","spec.clusterServiceClass.name":"cluster-service-class-name","spec.externalID":"external-id","spec.externalName":"external-plan-name","spec.free":"true"}`, }, } for _, tc := range cases { diff --git a/pkg/apis/servicecatalog/v1beta1/types.go b/pkg/apis/servicecatalog/v1beta1/types.go index e92bee01287..9987842a0d1 100644 --- a/pkg/apis/servicecatalog/v1beta1/types.go +++ b/pkg/apis/servicecatalog/v1beta1/types.go @@ -136,13 +136,13 @@ type CommonServiceBrokerSpec struct { // This is an example of a whitelist on service externalName. // Goal: Only list Services with the externalName of FooService and BarService, // Solution: restrictions := ServiceCatalogRestrictions{ -// ServiceClass: ["externalName in (FooService, BarService)"] +// ServiceClass: ["spec.externalName in (FooService, BarService)"] // } // // This is an example of a blacklist on service externalName. // Goal: Allow all services except the ones with the externalName of FooService and BarService, // Solution: restrictions := ServiceCatalogRestrictions{ -// ServiceClass: ["externalName notin (FooService, BarService)"] +// ServiceClass: ["spec.externalName notin (FooService, BarService)"] // } // // This whitelists plans called "Demo", and blacklists (but only a single element in @@ -150,7 +150,7 @@ type CommonServiceBrokerSpec struct { // Goal: Allow all plans with the externalName demo, but not AABBCC, and not a specific service by name, // Solution: restrictions := ServiceCatalogRestrictions{ // ServiceClass: ["name!=AABBB-CCDD-EEGG-HIJK"] -// ServicePlan: ["externalName in (Demo)", "name!=AABBCC"] +// ServicePlan: ["spec.externalName in (Demo)", "name!=AABBCC"] // } // // CatalogRestrictions strings have a special format similar to Label Selectors, @@ -171,8 +171,9 @@ type CommonServiceBrokerSpec struct { // name - the value set to [Cluster]ServicePlan.Name // spec.externalName - the value set to [Cluster]ServicePlan.Spec.ExternalName // spec.externalID - the value set to [Cluster]ServicePlan.Spec.ExternalID +// spec.free - the value set to [Cluster]ServicePlan.Spec.Free // spec.serviceClass.name - the value set to ServicePlan.Spec.ServiceClassRef.Name -// spec.clusterServiceClass.name - the vlaue set to ClusterServicePlan.Spec.ClusterServiceClassRef.Name +// spec.clusterServiceClass.name - the value set to ClusterServicePlan.Spec.ClusterServiceClassRef.Name type CatalogRestrictions struct { // ServiceClass represents a selector for plans, used to filter catalog re-lists. ServiceClass []string `json:"serviceClass,omitempty"` @@ -1372,6 +1373,8 @@ const ( FilterSpecClusterServiceClassName = "spec.clusterServiceClass.name" // SpecServiceClassName is only used for plans, the parent service class name. FilterSpecServiceClassName = "spec.serviceClass.name" + // FilterSpecFree is only used for plans, determines if the plan is free. + FilterSpecFree = "spec.free" ) // SecretTransform is a single transformation that is applied to the diff --git a/pkg/controller/controller_test.go b/pkg/controller/controller_test.go index ea38ab3430b..22fbfab8859 100644 --- a/pkg/controller/controller_test.go +++ b/pkg/controller/controller_test.go @@ -1588,6 +1588,15 @@ func TestConvertAndFilterCatalog(t *testing.T) { plans: []string{"Goldengrove", "Queensgate"}, catalog: largeTestCatalog, }, + { + name: "filter free plans", + restrictions: &v1beta1.CatalogRestrictions{ + ServicePlan: []string{"spec.free==true"}, + }, + classes: []string{"Arrax", "Balerion"}, + plans: []string{"Eastwatch-by-the-Sea", "OldOak", "Queensgate"}, + catalog: largeTestCatalog, + }, } for _, tc := range cases { t.Run(tc.name, func(t *testing.T) { diff --git a/pkg/openapi/openapi_generated.go b/pkg/openapi/openapi_generated.go index d0c7d38aee3..e031defd65b 100644 --- a/pkg/openapi/openapi_generated.go +++ b/pkg/openapi/openapi_generated.go @@ -441,7 +441,7 @@ func schema_pkg_apis_servicecatalog_v1beta1_CatalogRestrictions(ref common.Refer return common.OpenAPIDefinition{ Schema: spec.Schema{ SchemaProps: spec.SchemaProps{ - Description: "CatalogRestrictions is a set of restrictions on which of a broker's services and plans have resources created for them.\n\nSome examples of this object are as follows:\n\nThis is an example of a whitelist on service externalName. Goal: Only list Services with the externalName of FooService and BarService, Solution: restrictions := ServiceCatalogRestrictions{\n\t\tServiceClass: [\"externalName in (FooService, BarService)\"]\n}\n\nThis is an example of a blacklist on service externalName. Goal: Allow all services except the ones with the externalName of FooService and BarService, Solution: restrictions := ServiceCatalogRestrictions{\n\t\tServiceClass: [\"externalName notin (FooService, BarService)\"]\n}\n\nThis whitelists plans called \"Demo\", and blacklists (but only a single element in the list) a service and a plan. Goal: Allow all plans with the externalName demo, but not AABBCC, and not a specific service by name, Solution: restrictions := ServiceCatalogRestrictions{\n\t\tServiceClass: [\"name!=AABBB-CCDD-EEGG-HIJK\"]\n\t\tServicePlan: [\"externalName in (Demo)\", \"name!=AABBCC\"]\n}\n\nCatalogRestrictions strings have a special format similar to Label Selectors, except the catalog supports only a very specific property set.\n\nThe predicate format is expected to be `` Check the *Requirements type definition for which strings will be allowed. is allowed to be one of the following: ==, !=, in, notin will be a string value if `==` or `!=` are used. will be a set of string values if `in` or `notin` are used. Multiple predicates are allowed to be chained with a comma (,)\n\nServiceClass allowed property names:\n name - the value set to [Cluster]ServiceClass.Name\n spec.externalName - the value set to [Cluster]ServiceClass.Spec.ExternalName\n spec.externalID - the value set to [Cluster]ServiceClass.Spec.ExternalID\nServicePlan allowed property names:\n name - the value set to [Cluster]ServicePlan.Name\n spec.externalName - the value set to [Cluster]ServicePlan.Spec.ExternalName\n spec.externalID - the value set to [Cluster]ServicePlan.Spec.ExternalID\n spec.serviceClass.name - the value set to ServicePlan.Spec.ServiceClassRef.Name\n spec.clusterServiceClass.name - the vlaue set to ClusterServicePlan.Spec.ClusterServiceClassRef.Name", + Description: "CatalogRestrictions is a set of restrictions on which of a broker's services and plans have resources created for them.\n\nSome examples of this object are as follows:\n\nThis is an example of a whitelist on service externalName. Goal: Only list Services with the externalName of FooService and BarService, Solution: restrictions := ServiceCatalogRestrictions{\n\t\tServiceClass: [\"spec.externalName in (FooService, BarService)\"]\n}\n\nThis is an example of a blacklist on service externalName. Goal: Allow all services except the ones with the externalName of FooService and BarService, Solution: restrictions := ServiceCatalogRestrictions{\n\t\tServiceClass: [\"spec.externalName notin (FooService, BarService)\"]\n}\n\nThis whitelists plans called \"Demo\", and blacklists (but only a single element in the list) a service and a plan. Goal: Allow all plans with the externalName demo, but not AABBCC, and not a specific service by name, Solution: restrictions := ServiceCatalogRestrictions{\n\t\tServiceClass: [\"name!=AABBB-CCDD-EEGG-HIJK\"]\n\t\tServicePlan: [\"spec.externalName in (Demo)\", \"name!=AABBCC\"]\n}\n\nCatalogRestrictions strings have a special format similar to Label Selectors, except the catalog supports only a very specific property set.\n\nThe predicate format is expected to be `` Check the *Requirements type definition for which strings will be allowed. is allowed to be one of the following: ==, !=, in, notin will be a string value if `==` or `!=` are used. will be a set of string values if `in` or `notin` are used. Multiple predicates are allowed to be chained with a comma (,)\n\nServiceClass allowed property names:\n name - the value set to [Cluster]ServiceClass.Name\n spec.externalName - the value set to [Cluster]ServiceClass.Spec.ExternalName\n spec.externalID - the value set to [Cluster]ServiceClass.Spec.ExternalID\nServicePlan allowed property names:\n name - the value set to [Cluster]ServicePlan.Name\n spec.externalName - the value set to [Cluster]ServicePlan.Spec.ExternalName\n spec.externalID - the value set to [Cluster]ServicePlan.Spec.ExternalID\n spec.free - the value set to [Cluster]ServicePlan.Spec.Free\n spec.serviceClass.name - the value set to ServicePlan.Spec.ServiceClassRef.Name\n spec.clusterServiceClass.name - the value set to ClusterServicePlan.Spec.ClusterServiceClassRef.Name", Properties: map[string]spec.Schema{ "serviceClass": { SchemaProps: spec.SchemaProps{