Skip to content

Commit 485d5e6

Browse files
Ville Aikaskibbles-n-bytes
Ville Aikas
authored andcommitted
Add support for specifying plan using K8S names. (#1377)
* Add support for specifying plan using K8S names. * some wording clarifications and forgot to check in the admission controller file change * fix e2e tests
1 parent 662bba8 commit 485d5e6

File tree

13 files changed

+734
-50
lines changed

13 files changed

+734
-50
lines changed

pkg/apis/servicecatalog/types.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -431,6 +431,14 @@ type PlanReference struct {
431431
// the current name of the ClusterServicePlan, you should follow the
432432
// ClusterServicePlanRef below.
433433
ExternalClusterServicePlanName string
434+
435+
// ClusterServiceClassName is the kubernetes name of the
436+
// ClusterServiceClass.
437+
//
438+
// Immutable.
439+
ClusterServiceClassName string
440+
// ClusterServicePlanName is kubernetes name of the ClusterServicePlan.
441+
ClusterServicePlanName string
434442
}
435443

436444
// ServiceInstanceSpec represents the desired state of an Instance.

pkg/apis/servicecatalog/v1beta1/types.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -427,6 +427,13 @@ type ServiceInstance struct {
427427
// ServicePlan and ServiceClass. Because there are multiple ways to
428428
// specify the desired Class/Plan, this structure specifies the
429429
// allowed ways to specify the intent.
430+
//
431+
// Currently supported ways:
432+
// - ExternalClusterServiceClassName and ExternalClusterServicePlanName
433+
// - ClusterServiceClassName and ClusterServicePlanName
434+
//
435+
// For both of these ways, if a ClusterServiceClass only has one plan
436+
// then leaving the *ServicePlanName is optional.
430437
type PlanReference struct {
431438
// ExternalClusterServiceClassName is the human-readable name of the
432439
// service as reported by the broker. Note that if the broker changes
@@ -442,6 +449,14 @@ type PlanReference struct {
442449
// the current name of the ClusterServicePlan, you should follow the
443450
// ClusterServicePlanRef below.
444451
ExternalClusterServicePlanName string `json:"externalClusterServicePlanName,omitempty"`
452+
453+
// ClusterServiceClassName is the kubernetes name of the
454+
// ClusterServiceClass.
455+
//
456+
// Immutable.
457+
ClusterServiceClassName string `json:"clusterServiceClassName,omitempty"`
458+
// ClusterServicePlanName is kubernetes name of the ClusterServicePlan.
459+
ClusterServicePlanName string `json:"clusterServicePlanName,omitempty"`
445460
}
446461

447462
// ServiceInstanceSpec represents the desired state of an Instance.

pkg/apis/servicecatalog/v1beta1/zz_generated.conversion.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -501,6 +501,8 @@ func Convert_servicecatalog_ParametersFromSource_To_v1beta1_ParametersFromSource
501501
func autoConvert_v1beta1_PlanReference_To_servicecatalog_PlanReference(in *PlanReference, out *servicecatalog.PlanReference, s conversion.Scope) error {
502502
out.ExternalClusterServiceClassName = in.ExternalClusterServiceClassName
503503
out.ExternalClusterServicePlanName = in.ExternalClusterServicePlanName
504+
out.ClusterServiceClassName = in.ClusterServiceClassName
505+
out.ClusterServicePlanName = in.ClusterServicePlanName
504506
return nil
505507
}
506508

@@ -512,6 +514,8 @@ func Convert_v1beta1_PlanReference_To_servicecatalog_PlanReference(in *PlanRefer
512514
func autoConvert_servicecatalog_PlanReference_To_v1beta1_PlanReference(in *servicecatalog.PlanReference, out *PlanReference, s conversion.Scope) error {
513515
out.ExternalClusterServiceClassName = in.ExternalClusterServiceClassName
514516
out.ExternalClusterServicePlanName = in.ExternalClusterServicePlanName
517+
out.ClusterServiceClassName = in.ClusterServiceClassName
518+
out.ClusterServicePlanName = in.ClusterServicePlanName
515519
return nil
516520
}
517521

pkg/apis/servicecatalog/validation/instance.go

Lines changed: 66 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -68,19 +68,7 @@ func internalValidateServiceInstance(instance *sc.ServiceInstance, create bool)
6868
func validateServiceInstanceSpec(spec *sc.ServiceInstanceSpec, fldPath *field.Path, create bool) field.ErrorList {
6969
allErrs := field.ErrorList{}
7070

71-
if "" == spec.ExternalClusterServiceClassName {
72-
allErrs = append(allErrs, field.Required(fldPath.Child("externalClusterServiceClassName"), "externalClusterServiceClassName is required"))
73-
}
74-
for _, msg := range validateServiceClassName(spec.ExternalClusterServiceClassName, false /* prefix */) {
75-
allErrs = append(allErrs, field.Invalid(fldPath.Child("externalClusterServiceClassName"), spec.ExternalClusterServiceClassName, msg))
76-
}
77-
78-
if "" == spec.ExternalClusterServicePlanName {
79-
allErrs = append(allErrs, field.Required(fldPath.Child("externalClusterServicePlanName"), "externalClusterServicePlanName is required"))
80-
}
81-
for _, msg := range validateServicePlanName(spec.ExternalClusterServicePlanName, false /* prefix */) {
82-
allErrs = append(allErrs, field.Invalid(fldPath.Child("externalClusterServicePlanName"), spec.ExternalClusterServicePlanName, msg))
83-
}
71+
allErrs = append(allErrs, validatePlanReference(&spec.PlanReference, fldPath)...)
8472

8573
if spec.ParametersFrom != nil {
8674
for _, paramsFrom := range spec.ParametersFrom {
@@ -252,14 +240,17 @@ func internalValidateServiceInstanceUpdateAllowed(new *sc.ServiceInstance, old *
252240
func ValidateServiceInstanceUpdate(new *sc.ServiceInstance, old *sc.ServiceInstance) field.ErrorList {
253241
allErrs := field.ErrorList{}
254242

243+
specFieldPath := field.NewPath("spec")
244+
245+
allErrs = append(allErrs, validatePlanReferenceUpdate(&new.Spec.PlanReference, &old.Spec.PlanReference, specFieldPath)...)
255246
allErrs = append(allErrs, internalValidateServiceInstanceUpdateAllowed(new, old)...)
256247
allErrs = append(allErrs, internalValidateServiceInstance(new, false)...)
257248

258-
allErrs = append(allErrs, apivalidation.ValidateImmutableField(new.Spec.ExternalClusterServiceClassName, old.Spec.ExternalClusterServiceClassName, field.NewPath("spec").Child("externalClusterServiceClassName"))...)
259-
allErrs = append(allErrs, apivalidation.ValidateImmutableField(new.Spec.ExternalID, old.Spec.ExternalID, field.NewPath("spec").Child("externalID"))...)
249+
allErrs = append(allErrs, apivalidation.ValidateImmutableField(new.Spec.ExternalClusterServiceClassName, old.Spec.ExternalClusterServiceClassName, specFieldPath.Child("externalClusterServiceClassName"))...)
250+
allErrs = append(allErrs, apivalidation.ValidateImmutableField(new.Spec.ExternalID, old.Spec.ExternalID, specFieldPath.Child("externalID"))...)
260251

261252
if new.Spec.UpdateRequests < old.Spec.UpdateRequests {
262-
allErrs = append(allErrs, field.Invalid(field.NewPath("spec").Child("updateRequests"), new.Spec.UpdateRequests, "new updateRequests value must not be less than the old one"))
253+
allErrs = append(allErrs, field.Invalid(specFieldPath.Child("updateRequests"), new.Spec.UpdateRequests, "new updateRequests value must not be less than the old one"))
263254
}
264255

265256
return allErrs
@@ -309,3 +300,62 @@ func ValidateServiceInstanceReferencesUpdate(new *sc.ServiceInstance, old *sc.Se
309300
allErrs = append(allErrs, internalValidateServiceInstance(new, false)...)
310301
return allErrs
311302
}
303+
304+
func validatePlanReference(p *sc.PlanReference, fldPath *field.Path) field.ErrorList {
305+
allErrs := field.ErrorList{}
306+
307+
// Just to make reading of the conditionals in the code easier.
308+
externalClassSet := p.ExternalClusterServiceClassName != ""
309+
externalPlanSet := p.ExternalClusterServicePlanName != ""
310+
k8sClassSet := p.ClusterServiceClassName != ""
311+
k8sPlanSet := p.ClusterServicePlanName != ""
312+
313+
// Can't specify both External and k8s name but must specify one.
314+
if externalClassSet == k8sClassSet {
315+
allErrs = append(allErrs, field.Required(fldPath.Child("externalClusterServiceClassName"), "exactly one of externalClusterServiceClassName or clusterServiceClassName required"))
316+
allErrs = append(allErrs, field.Required(fldPath.Child("clusterServiceClassName"), "exactly one of externalClusterServiceClassName or clusterServiceClassName required"))
317+
}
318+
// Can't specify both External and k8s name but must specify one.
319+
if externalPlanSet == k8sPlanSet {
320+
allErrs = append(allErrs, field.Required(fldPath.Child("externalClusterServicePlanName"), "either externalClusterServicePlanName or clusterServicePlanName required"))
321+
allErrs = append(allErrs, field.Required(fldPath.Child("clusterServicePlanName"), "exactly one of externalClusterServicePlanName or clusterServicePlanName required"))
322+
}
323+
324+
if externalClassSet {
325+
for _, msg := range validateServiceClassName(p.ExternalClusterServiceClassName, false /* prefix */) {
326+
allErrs = append(allErrs, field.Invalid(fldPath.Child("externalClusterServiceClassName"), p.ExternalClusterServiceClassName, msg))
327+
}
328+
329+
// If ExternalClusterServiceClassName given, must use ExternalClusterServicePlanName
330+
if !externalPlanSet {
331+
allErrs = append(allErrs, field.Required(fldPath.Child("externalClusterServicePlanName"), "must specify externalClusterServicePlanName with externalClusterServiceClassName"))
332+
}
333+
334+
for _, msg := range validateServicePlanName(p.ExternalClusterServicePlanName, false /* prefix */) {
335+
allErrs = append(allErrs, field.Invalid(fldPath.Child("externalClusterServicePlanName"), p.ClusterServicePlanName, msg))
336+
}
337+
}
338+
if k8sClassSet {
339+
for _, msg := range validateServiceClassName(p.ClusterServiceClassName, false /* prefix */) {
340+
allErrs = append(allErrs, field.Invalid(fldPath.Child("clusterServiceClassName"), p.ClusterServiceClassName, msg))
341+
}
342+
343+
// If ClusterServiceClassName given, must use ClusterServicePlanName
344+
if !k8sPlanSet {
345+
allErrs = append(allErrs, field.Required(fldPath.Child("clusterServicePlanName"), "must specify clusterServicePlanName with clusterServiceClassName"))
346+
}
347+
for _, msg := range validateServicePlanName(p.ClusterServicePlanName, false /* prefix */) {
348+
allErrs = append(allErrs, field.Invalid(fldPath.Child("clusterServicePlanName"), p.ClusterServicePlanName, msg))
349+
}
350+
}
351+
return allErrs
352+
}
353+
354+
func validatePlanReferenceUpdate(pOld *sc.PlanReference, pNew *sc.PlanReference, fldPath *field.Path) field.ErrorList {
355+
allErrs := field.ErrorList{}
356+
allErrs = append(allErrs, validatePlanReference(pOld, fldPath)...)
357+
allErrs = append(allErrs, validatePlanReference(pNew, fldPath)...)
358+
allErrs = append(allErrs, apivalidation.ValidateImmutableField(pNew.ExternalClusterServiceClassName, pOld.ExternalClusterServiceClassName, field.NewPath("spec").Child("externalClusterServiceClassName"))...)
359+
allErrs = append(allErrs, apivalidation.ValidateImmutableField(pNew.ClusterServiceClassName, pOld.ClusterServiceClassName, field.NewPath("spec").Child("clusterServiceClassName"))...)
360+
return allErrs
361+
}

0 commit comments

Comments
 (0)