From be82b7054634fae5a9ced1e6f2968e80273a271d Mon Sep 17 00:00:00 2001 From: staebler Date: Tue, 5 Sep 2017 16:41:09 -0400 Subject: [PATCH] Store in-progress and external properties in instance and binding status. --- pkg/apis/servicecatalog/testing/fuzzer.go | 18 + pkg/apis/servicecatalog/types.go | 50 + .../v1alpha1/types.generated.go | 2741 +++++++++++------ pkg/apis/servicecatalog/v1alpha1/types.go | 50 + .../v1alpha1/zz_generated.conversion.go | 62 + .../v1alpha1/zz_generated.deepcopy.go | 80 + pkg/apis/servicecatalog/validation/binding.go | 104 +- .../servicecatalog/validation/binding_test.go | 270 ++ .../servicecatalog/validation/instance.go | 105 +- .../validation/instance_test.go | 468 ++- .../servicecatalog/validation/validation.go | 27 + .../servicecatalog/zz_generated.deepcopy.go | 80 + pkg/controller/controller_binding.go | 60 +- pkg/controller/controller_binding_test.go | 235 +- pkg/controller/controller_instance.go | 60 +- pkg/controller/controller_instance_test.go | 206 +- pkg/controller/controller_test.go | 342 +- pkg/controller/parameters.go | 39 +- pkg/controller/parameters_test.go | 93 +- pkg/openapi/openapi_generated.go | 96 +- 20 files changed, 4026 insertions(+), 1160 deletions(-) create mode 100644 pkg/apis/servicecatalog/validation/validation.go diff --git a/pkg/apis/servicecatalog/testing/fuzzer.go b/pkg/apis/servicecatalog/testing/fuzzer.go index 95dd84e2975..69a2c986884 100644 --- a/pkg/apis/servicecatalog/testing/fuzzer.go +++ b/pkg/apis/servicecatalog/testing/fuzzer.go @@ -225,6 +225,24 @@ func FuzzerFor(t *testing.T, version schema.GroupVersion, src rand.Source) *fuzz } bs.Parameters = parameters }, + func(bs *servicecatalog.ServiceInstancePropertiesState, c fuzz.Continue) { + c.FuzzNoCustom(bs) + parameters, err := createParameter(c) + if err != nil { + t.Errorf("Failed to create parameter object: %v", err) + return + } + bs.Parameters = parameters + }, + func(bs *servicecatalog.ServiceInstanceCredentialPropertiesState, c fuzz.Continue) { + c.FuzzNoCustom(bs) + parameters, err := createParameter(c) + if err != nil { + t.Errorf("Failed to create parameter object: %v", err) + return + } + bs.Parameters = parameters + }, func(sc *servicecatalog.ServiceClass, c fuzz.Continue) { c.FuzzNoCustom(sc) metadata, err := createServiceMetadata(c) diff --git a/pkg/apis/servicecatalog/types.go b/pkg/apis/servicecatalog/types.go index a1084af8c6e..c5b457321eb 100644 --- a/pkg/apis/servicecatalog/types.go +++ b/pkg/apis/servicecatalog/types.go @@ -458,6 +458,14 @@ type ServiceInstanceStatus struct { // OperationStartTime is the time at which the current operation began. OperationStartTime *metav1.Time + + // InProgressProperties is the properties state for which there is a + // provision or update action in progress. + InProgressProperties *ServiceInstancePropertiesState + + // ExternalProperties is the properites state which the broker knows + // about. + ExternalProperties *ServiceInstancePropertiesState } // ServiceInstanceCondition contains condition information about an Instance. @@ -510,6 +518,25 @@ const ( ServiceInstanceOperationDeprovision ServiceInstanceOperation = "Deprovision" ) +// ServiceInstancePropertiesState is the state of a ServiceInstance that +// the ServiceBroker knows about. +type ServiceInstancePropertiesState struct { + // PlanName is the name of the plan that the broker knows this + // ServiceInstance to be on. + PlanName string + + // Parameters is a blob of the parameters and their values that the broker + // knows about for this ServiceInstance. If a parameter was sourced from + // a secret, its value will be "" in this blob. + Parameters *runtime.RawExtension + + // ParametersChecksum is the checksum of the parameters that were sent. + ParametersChecksum string + + // UserInfo is information about the user that made the request. + UserInfo *UserInfo +} + // ServiceInstanceCredentialList is a list of ServiceInstanceCredentials. type ServiceInstanceCredentialList struct { metav1.TypeMeta @@ -593,6 +620,14 @@ type ServiceInstanceCredentialStatus struct { // OperationStartTime is the time at which the current operation began. OperationStartTime *metav1.Time + + // InProgressProperties is the properties state for which there is a bind + // operation in progress. + InProgressProperties *ServiceInstanceCredentialPropertiesState + + // ExternalProperties is the properties state that the broker knows + // about for this ServiceInstanceCredential. + ExternalProperties *ServiceInstanceCredentialPropertiesState } // ServiceInstanceCredentialCondition condition information for a ServiceInstanceCredential. @@ -646,6 +681,21 @@ const ( FinalizerServiceCatalog string = "kubernetes-incubator/service-catalog" ) +// ServiceInstanceCredentialPropertiesState is the state of a +// ServiceInstanceCredential that the ServiceBroker knows about. +type ServiceInstanceCredentialPropertiesState struct { + // Parameters is a blob of the parameters and their values that the broker + // knows about for this ServiceInstanceCredential. If a parameter was + // sourced from a secret, its value will be "" in this blob. + Parameters *runtime.RawExtension + + // ParametersChecksum is the checksum of the parameters that were sent. + ParametersChecksum string + + // UserInfo is information about the user that made the request. + UserInfo *UserInfo +} + // ParametersFromSource represents the source of a set of Parameters type ParametersFromSource struct { // The Secret key to select from. diff --git a/pkg/apis/servicecatalog/v1alpha1/types.generated.go b/pkg/apis/servicecatalog/v1alpha1/types.generated.go index b70fb4038ac..b9bb81b1520 100644 --- a/pkg/apis/servicecatalog/v1alpha1/types.generated.go +++ b/pkg/apis/servicecatalog/v1alpha1/types.generated.go @@ -7274,16 +7274,18 @@ func (x *ServiceInstanceStatus) CodecEncodeSelf(e *codec1978.Encoder) { } else { yysep2 := !z.EncBinary() yy2arr2 := z.EncBasicHandle().StructToArray - var yyq2 [7]bool + var yyq2 [9]bool _, _, _ = yysep2, yyq2, yy2arr2 const yyr2 bool = false yyq2[2] = x.LastOperation != nil yyq2[3] = x.DashboardURL != nil yyq2[4] = x.CurrentOperation != "" yyq2[6] = x.OperationStartTime != nil + yyq2[7] = x.InProgressProperties != nil + yyq2[8] = x.ExternalProperties != nil var yynn2 int if yyr2 || yy2arr2 { - r.EncodeArrayStart(7) + r.EncodeArrayStart(9) } else { yynn2 = 3 for _, b := range yyq2 { @@ -7487,6 +7489,52 @@ func (x *ServiceInstanceStatus) CodecEncodeSelf(e *codec1978.Encoder) { } } } + if yyr2 || yy2arr2 { + z.EncSendContainerState(codecSelfer_containerArrayElem1234) + if yyq2[7] { + if x.InProgressProperties == nil { + r.EncodeNil() + } else { + x.InProgressProperties.CodecEncodeSelf(e) + } + } else { + r.EncodeNil() + } + } else { + if yyq2[7] { + z.EncSendContainerState(codecSelfer_containerMapKey1234) + r.EncodeString(codecSelferC_UTF81234, string("inProgressProperties")) + z.EncSendContainerState(codecSelfer_containerMapValue1234) + if x.InProgressProperties == nil { + r.EncodeNil() + } else { + x.InProgressProperties.CodecEncodeSelf(e) + } + } + } + if yyr2 || yy2arr2 { + z.EncSendContainerState(codecSelfer_containerArrayElem1234) + if yyq2[8] { + if x.ExternalProperties == nil { + r.EncodeNil() + } else { + x.ExternalProperties.CodecEncodeSelf(e) + } + } else { + r.EncodeNil() + } + } else { + if yyq2[8] { + z.EncSendContainerState(codecSelfer_containerMapKey1234) + r.EncodeString(codecSelferC_UTF81234, string("externalProperties")) + z.EncSendContainerState(codecSelfer_containerMapValue1234) + if x.ExternalProperties == nil { + r.EncodeNil() + } else { + x.ExternalProperties.CodecEncodeSelf(e) + } + } + } if yyr2 || yy2arr2 { z.EncSendContainerState(codecSelfer_containerArrayEnd1234) } else { @@ -7644,6 +7692,28 @@ func (x *ServiceInstanceStatus) codecDecodeSelfFromMap(l int, d *codec1978.Decod z.DecFallback(x.OperationStartTime, false) } } + case "inProgressProperties": + if r.TryDecodeAsNil() { + if x.InProgressProperties != nil { + x.InProgressProperties = nil + } + } else { + if x.InProgressProperties == nil { + x.InProgressProperties = new(ServiceInstancePropertiesState) + } + x.InProgressProperties.CodecDecodeSelf(d) + } + case "externalProperties": + if r.TryDecodeAsNil() { + if x.ExternalProperties != nil { + x.ExternalProperties = nil + } + } else { + if x.ExternalProperties == nil { + x.ExternalProperties = new(ServiceInstancePropertiesState) + } + x.ExternalProperties.CodecDecodeSelf(d) + } default: z.DecStructFieldNotFound(-1, yys3) } // end switch yys3 @@ -7655,16 +7725,16 @@ func (x *ServiceInstanceStatus) codecDecodeSelfFromArray(l int, d *codec1978.Dec var h codecSelfer1234 z, r := codec1978.GenHelperDecoder(d) _, _, _ = h, z, r - var yyj17 int - var yyb17 bool - var yyhl17 bool = l >= 0 - yyj17++ - if yyhl17 { - yyb17 = yyj17 > l + var yyj19 int + var yyb19 bool + var yyhl19 bool = l >= 0 + yyj19++ + if yyhl19 { + yyb19 = yyj19 > l } else { - yyb17 = r.CheckBreak() + yyb19 = r.CheckBreak() } - if yyb17 { + if yyb19 { z.DecSendContainerState(codecSelfer_containerArrayEnd1234) return } @@ -7672,21 +7742,21 @@ func (x *ServiceInstanceStatus) codecDecodeSelfFromArray(l int, d *codec1978.Dec if r.TryDecodeAsNil() { x.Conditions = nil } else { - yyv18 := &x.Conditions - yym19 := z.DecBinary() - _ = yym19 + yyv20 := &x.Conditions + yym21 := z.DecBinary() + _ = yym21 if false { } else { - h.decSliceServiceInstanceCondition((*[]ServiceInstanceCondition)(yyv18), d) + h.decSliceServiceInstanceCondition((*[]ServiceInstanceCondition)(yyv20), d) } } - yyj17++ - if yyhl17 { - yyb17 = yyj17 > l + yyj19++ + if yyhl19 { + yyb19 = yyj19 > l } else { - yyb17 = r.CheckBreak() + yyb19 = r.CheckBreak() } - if yyb17 { + if yyb19 { z.DecSendContainerState(codecSelfer_containerArrayEnd1234) return } @@ -7694,21 +7764,21 @@ func (x *ServiceInstanceStatus) codecDecodeSelfFromArray(l int, d *codec1978.Dec if r.TryDecodeAsNil() { x.AsyncOpInProgress = false } else { - yyv20 := &x.AsyncOpInProgress - yym21 := z.DecBinary() - _ = yym21 + yyv22 := &x.AsyncOpInProgress + yym23 := z.DecBinary() + _ = yym23 if false { } else { - *((*bool)(yyv20)) = r.DecodeBool() + *((*bool)(yyv22)) = r.DecodeBool() } } - yyj17++ - if yyhl17 { - yyb17 = yyj17 > l + yyj19++ + if yyhl19 { + yyb19 = yyj19 > l } else { - yyb17 = r.CheckBreak() + yyb19 = r.CheckBreak() } - if yyb17 { + if yyb19 { z.DecSendContainerState(codecSelfer_containerArrayEnd1234) return } @@ -7721,20 +7791,20 @@ func (x *ServiceInstanceStatus) codecDecodeSelfFromArray(l int, d *codec1978.Dec if x.LastOperation == nil { x.LastOperation = new(string) } - yym23 := z.DecBinary() - _ = yym23 + yym25 := z.DecBinary() + _ = yym25 if false { } else { *((*string)(x.LastOperation)) = r.DecodeString() } } - yyj17++ - if yyhl17 { - yyb17 = yyj17 > l + yyj19++ + if yyhl19 { + yyb19 = yyj19 > l } else { - yyb17 = r.CheckBreak() + yyb19 = r.CheckBreak() } - if yyb17 { + if yyb19 { z.DecSendContainerState(codecSelfer_containerArrayEnd1234) return } @@ -7747,20 +7817,20 @@ func (x *ServiceInstanceStatus) codecDecodeSelfFromArray(l int, d *codec1978.Dec if x.DashboardURL == nil { x.DashboardURL = new(string) } - yym25 := z.DecBinary() - _ = yym25 + yym27 := z.DecBinary() + _ = yym27 if false { } else { *((*string)(x.DashboardURL)) = r.DecodeString() } } - yyj17++ - if yyhl17 { - yyb17 = yyj17 > l + yyj19++ + if yyhl19 { + yyb19 = yyj19 > l } else { - yyb17 = r.CheckBreak() + yyb19 = r.CheckBreak() } - if yyb17 { + if yyb19 { z.DecSendContainerState(codecSelfer_containerArrayEnd1234) return } @@ -7768,16 +7838,16 @@ func (x *ServiceInstanceStatus) codecDecodeSelfFromArray(l int, d *codec1978.Dec if r.TryDecodeAsNil() { x.CurrentOperation = "" } else { - yyv26 := &x.CurrentOperation - yyv26.CodecDecodeSelf(d) + yyv28 := &x.CurrentOperation + yyv28.CodecDecodeSelf(d) } - yyj17++ - if yyhl17 { - yyb17 = yyj17 > l + yyj19++ + if yyhl19 { + yyb19 = yyj19 > l } else { - yyb17 = r.CheckBreak() + yyb19 = r.CheckBreak() } - if yyb17 { + if yyb19 { z.DecSendContainerState(codecSelfer_containerArrayEnd1234) return } @@ -7785,21 +7855,21 @@ func (x *ServiceInstanceStatus) codecDecodeSelfFromArray(l int, d *codec1978.Dec if r.TryDecodeAsNil() { x.ReconciledGeneration = 0 } else { - yyv27 := &x.ReconciledGeneration - yym28 := z.DecBinary() - _ = yym28 + yyv29 := &x.ReconciledGeneration + yym30 := z.DecBinary() + _ = yym30 if false { } else { - *((*int64)(yyv27)) = int64(r.DecodeInt(64)) + *((*int64)(yyv29)) = int64(r.DecodeInt(64)) } } - yyj17++ - if yyhl17 { - yyb17 = yyj17 > l + yyj19++ + if yyhl19 { + yyb19 = yyj19 > l } else { - yyb17 = r.CheckBreak() + yyb19 = r.CheckBreak() } - if yyb17 { + if yyb19 { z.DecSendContainerState(codecSelfer_containerArrayEnd1234) return } @@ -7812,30 +7882,72 @@ func (x *ServiceInstanceStatus) codecDecodeSelfFromArray(l int, d *codec1978.Dec if x.OperationStartTime == nil { x.OperationStartTime = new(pkg1_v1.Time) } - yym30 := z.DecBinary() - _ = yym30 + yym32 := z.DecBinary() + _ = yym32 if false { } else if z.HasExtensions() && z.DecExt(x.OperationStartTime) { - } else if yym30 { + } else if yym32 { z.DecBinaryUnmarshal(x.OperationStartTime) - } else if !yym30 && z.IsJSONHandle() { + } else if !yym32 && z.IsJSONHandle() { z.DecJSONUnmarshal(x.OperationStartTime) } else { z.DecFallback(x.OperationStartTime, false) } } + yyj19++ + if yyhl19 { + yyb19 = yyj19 > l + } else { + yyb19 = r.CheckBreak() + } + if yyb19 { + z.DecSendContainerState(codecSelfer_containerArrayEnd1234) + return + } + z.DecSendContainerState(codecSelfer_containerArrayElem1234) + if r.TryDecodeAsNil() { + if x.InProgressProperties != nil { + x.InProgressProperties = nil + } + } else { + if x.InProgressProperties == nil { + x.InProgressProperties = new(ServiceInstancePropertiesState) + } + x.InProgressProperties.CodecDecodeSelf(d) + } + yyj19++ + if yyhl19 { + yyb19 = yyj19 > l + } else { + yyb19 = r.CheckBreak() + } + if yyb19 { + z.DecSendContainerState(codecSelfer_containerArrayEnd1234) + return + } + z.DecSendContainerState(codecSelfer_containerArrayElem1234) + if r.TryDecodeAsNil() { + if x.ExternalProperties != nil { + x.ExternalProperties = nil + } + } else { + if x.ExternalProperties == nil { + x.ExternalProperties = new(ServiceInstancePropertiesState) + } + x.ExternalProperties.CodecDecodeSelf(d) + } for { - yyj17++ - if yyhl17 { - yyb17 = yyj17 > l + yyj19++ + if yyhl19 { + yyb19 = yyj19 > l } else { - yyb17 = r.CheckBreak() + yyb19 = r.CheckBreak() } - if yyb17 { + if yyb19 { break } z.DecSendContainerState(codecSelfer_containerArrayElem1234) - z.DecStructFieldNotFound(yyj17-1, "") + z.DecStructFieldNotFound(yyj19-1, "") } z.DecSendContainerState(codecSelfer_containerArrayEnd1234) } @@ -8260,7 +8372,7 @@ func (x *ServiceInstanceOperation) CodecDecodeSelf(d *codec1978.Decoder) { } } -func (x *ServiceInstanceCredentialList) CodecEncodeSelf(e *codec1978.Encoder) { +func (x *ServiceInstancePropertiesState) CodecEncodeSelf(e *codec1978.Encoder) { var h codecSelfer1234 z, r := codec1978.GenHelperEncoder(e) _, _, _ = h, z, r @@ -8277,9 +8389,9 @@ func (x *ServiceInstanceCredentialList) CodecEncodeSelf(e *codec1978.Encoder) { var yyq2 [4]bool _, _, _ = yysep2, yyq2, yy2arr2 const yyr2 bool = false - yyq2[0] = x.Kind != "" - yyq2[1] = x.APIVersion != "" - yyq2[2] = true + yyq2[1] = x.Parameters != nil + yyq2[2] = x.ParametersChecksum != "" + yyq2[3] = x.UserInfo != nil var yynn2 int if yyr2 || yy2arr2 { r.EncodeArrayStart(4) @@ -8295,107 +8407,107 @@ func (x *ServiceInstanceCredentialList) CodecEncodeSelf(e *codec1978.Encoder) { } if yyr2 || yy2arr2 { z.EncSendContainerState(codecSelfer_containerArrayElem1234) - if yyq2[0] { - yym4 := z.EncBinary() - _ = yym4 - if false { - } else { - r.EncodeString(codecSelferC_UTF81234, string(x.Kind)) - } + yym4 := z.EncBinary() + _ = yym4 + if false { } else { - r.EncodeString(codecSelferC_UTF81234, "") + r.EncodeString(codecSelferC_UTF81234, string(x.PlanName)) } } else { - if yyq2[0] { - z.EncSendContainerState(codecSelfer_containerMapKey1234) - r.EncodeString(codecSelferC_UTF81234, string("kind")) - z.EncSendContainerState(codecSelfer_containerMapValue1234) - yym5 := z.EncBinary() - _ = yym5 - if false { - } else { - r.EncodeString(codecSelferC_UTF81234, string(x.Kind)) - } + z.EncSendContainerState(codecSelfer_containerMapKey1234) + r.EncodeString(codecSelferC_UTF81234, string("planName")) + z.EncSendContainerState(codecSelfer_containerMapValue1234) + yym5 := z.EncBinary() + _ = yym5 + if false { + } else { + r.EncodeString(codecSelferC_UTF81234, string(x.PlanName)) } } if yyr2 || yy2arr2 { z.EncSendContainerState(codecSelfer_containerArrayElem1234) if yyq2[1] { - yym7 := z.EncBinary() - _ = yym7 - if false { + if x.Parameters == nil { + r.EncodeNil() } else { - r.EncodeString(codecSelferC_UTF81234, string(x.APIVersion)) + yym7 := z.EncBinary() + _ = yym7 + if false { + } else if z.HasExtensions() && z.EncExt(x.Parameters) { + } else if !yym7 && z.IsJSONHandle() { + z.EncJSONMarshal(x.Parameters) + } else { + z.EncFallback(x.Parameters) + } } } else { - r.EncodeString(codecSelferC_UTF81234, "") + r.EncodeNil() } } else { if yyq2[1] { z.EncSendContainerState(codecSelfer_containerMapKey1234) - r.EncodeString(codecSelferC_UTF81234, string("apiVersion")) + r.EncodeString(codecSelferC_UTF81234, string("parameters")) z.EncSendContainerState(codecSelfer_containerMapValue1234) - yym8 := z.EncBinary() - _ = yym8 - if false { + if x.Parameters == nil { + r.EncodeNil() } else { - r.EncodeString(codecSelferC_UTF81234, string(x.APIVersion)) + yym8 := z.EncBinary() + _ = yym8 + if false { + } else if z.HasExtensions() && z.EncExt(x.Parameters) { + } else if !yym8 && z.IsJSONHandle() { + z.EncJSONMarshal(x.Parameters) + } else { + z.EncFallback(x.Parameters) + } } } } if yyr2 || yy2arr2 { z.EncSendContainerState(codecSelfer_containerArrayElem1234) if yyq2[2] { - yy10 := &x.ListMeta - yym11 := z.EncBinary() - _ = yym11 + yym10 := z.EncBinary() + _ = yym10 if false { - } else if z.HasExtensions() && z.EncExt(yy10) { } else { - z.EncFallback(yy10) + r.EncodeString(codecSelferC_UTF81234, string(x.ParametersChecksum)) } } else { - r.EncodeNil() + r.EncodeString(codecSelferC_UTF81234, "") } } else { if yyq2[2] { z.EncSendContainerState(codecSelfer_containerMapKey1234) - r.EncodeString(codecSelferC_UTF81234, string("metadata")) + r.EncodeString(codecSelferC_UTF81234, string("parameterChecksum")) z.EncSendContainerState(codecSelfer_containerMapValue1234) - yy12 := &x.ListMeta - yym13 := z.EncBinary() - _ = yym13 + yym11 := z.EncBinary() + _ = yym11 if false { - } else if z.HasExtensions() && z.EncExt(yy12) { } else { - z.EncFallback(yy12) + r.EncodeString(codecSelferC_UTF81234, string(x.ParametersChecksum)) } } } if yyr2 || yy2arr2 { z.EncSendContainerState(codecSelfer_containerArrayElem1234) - if x.Items == nil { - r.EncodeNil() - } else { - yym15 := z.EncBinary() - _ = yym15 - if false { + if yyq2[3] { + if x.UserInfo == nil { + r.EncodeNil() } else { - h.encSliceServiceInstanceCredential(([]ServiceInstanceCredential)(x.Items), e) + x.UserInfo.CodecEncodeSelf(e) } + } else { + r.EncodeNil() } } else { - z.EncSendContainerState(codecSelfer_containerMapKey1234) - r.EncodeString(codecSelferC_UTF81234, string("items")) - z.EncSendContainerState(codecSelfer_containerMapValue1234) - if x.Items == nil { - r.EncodeNil() - } else { - yym16 := z.EncBinary() - _ = yym16 - if false { + if yyq2[3] { + z.EncSendContainerState(codecSelfer_containerMapKey1234) + r.EncodeString(codecSelferC_UTF81234, string("userInfo")) + z.EncSendContainerState(codecSelfer_containerMapValue1234) + if x.UserInfo == nil { + r.EncodeNil() } else { - h.encSliceServiceInstanceCredential(([]ServiceInstanceCredential)(x.Items), e) + x.UserInfo.CodecEncodeSelf(e) } } } @@ -8408,7 +8520,7 @@ func (x *ServiceInstanceCredentialList) CodecEncodeSelf(e *codec1978.Encoder) { } } -func (x *ServiceInstanceCredentialList) CodecDecodeSelf(d *codec1978.Decoder) { +func (x *ServiceInstancePropertiesState) CodecDecodeSelf(d *codec1978.Decoder) { var h codecSelfer1234 z, r := codec1978.GenHelperDecoder(d) _, _, _ = h, z, r @@ -8438,7 +8550,7 @@ func (x *ServiceInstanceCredentialList) CodecDecodeSelf(d *codec1978.Decoder) { } } -func (x *ServiceInstanceCredentialList) codecDecodeSelfFromMap(l int, d *codec1978.Decoder) { +func (x *ServiceInstancePropertiesState) codecDecodeSelfFromMap(l int, d *codec1978.Decoder) { var h codecSelfer1234 z, r := codec1978.GenHelperDecoder(d) _, _, _ = h, z, r @@ -8460,11 +8572,11 @@ func (x *ServiceInstanceCredentialList) codecDecodeSelfFromMap(l int, d *codec19 yys3 := string(yys3Slc) z.DecSendContainerState(codecSelfer_containerMapValue1234) switch yys3 { - case "kind": + case "planName": if r.TryDecodeAsNil() { - x.Kind = "" + x.PlanName = "" } else { - yyv4 := &x.Kind + yyv4 := &x.PlanName yym5 := z.DecBinary() _ = yym5 if false { @@ -8472,42 +8584,47 @@ func (x *ServiceInstanceCredentialList) codecDecodeSelfFromMap(l int, d *codec19 *((*string)(yyv4)) = r.DecodeString() } } - case "apiVersion": + case "parameters": if r.TryDecodeAsNil() { - x.APIVersion = "" + if x.Parameters != nil { + x.Parameters = nil + } } else { - yyv6 := &x.APIVersion + if x.Parameters == nil { + x.Parameters = new(pkg4_runtime.RawExtension) + } yym7 := z.DecBinary() _ = yym7 if false { + } else if z.HasExtensions() && z.DecExt(x.Parameters) { + } else if !yym7 && z.IsJSONHandle() { + z.DecJSONUnmarshal(x.Parameters) } else { - *((*string)(yyv6)) = r.DecodeString() + z.DecFallback(x.Parameters, false) } } - case "metadata": + case "parameterChecksum": if r.TryDecodeAsNil() { - x.ListMeta = pkg1_v1.ListMeta{} + x.ParametersChecksum = "" } else { - yyv8 := &x.ListMeta + yyv8 := &x.ParametersChecksum yym9 := z.DecBinary() _ = yym9 if false { - } else if z.HasExtensions() && z.DecExt(yyv8) { } else { - z.DecFallback(yyv8, false) + *((*string)(yyv8)) = r.DecodeString() } } - case "items": + case "userInfo": if r.TryDecodeAsNil() { - x.Items = nil + if x.UserInfo != nil { + x.UserInfo = nil + } } else { - yyv10 := &x.Items - yym11 := z.DecBinary() - _ = yym11 - if false { - } else { - h.decSliceServiceInstanceCredential((*[]ServiceInstanceCredential)(yyv10), d) + if x.UserInfo == nil { + x.UserInfo = new(UserInfo) } + x.UserInfo.CodecDecodeSelf(d) } default: z.DecStructFieldNotFound(-1, yys3) @@ -8516,119 +8633,124 @@ func (x *ServiceInstanceCredentialList) codecDecodeSelfFromMap(l int, d *codec19 z.DecSendContainerState(codecSelfer_containerMapEnd1234) } -func (x *ServiceInstanceCredentialList) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) { +func (x *ServiceInstancePropertiesState) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) { var h codecSelfer1234 z, r := codec1978.GenHelperDecoder(d) _, _, _ = h, z, r - var yyj12 int - var yyb12 bool - var yyhl12 bool = l >= 0 - yyj12++ - if yyhl12 { - yyb12 = yyj12 > l + var yyj11 int + var yyb11 bool + var yyhl11 bool = l >= 0 + yyj11++ + if yyhl11 { + yyb11 = yyj11 > l } else { - yyb12 = r.CheckBreak() + yyb11 = r.CheckBreak() } - if yyb12 { + if yyb11 { z.DecSendContainerState(codecSelfer_containerArrayEnd1234) return } z.DecSendContainerState(codecSelfer_containerArrayElem1234) if r.TryDecodeAsNil() { - x.Kind = "" + x.PlanName = "" } else { - yyv13 := &x.Kind - yym14 := z.DecBinary() - _ = yym14 + yyv12 := &x.PlanName + yym13 := z.DecBinary() + _ = yym13 if false { } else { - *((*string)(yyv13)) = r.DecodeString() + *((*string)(yyv12)) = r.DecodeString() } } - yyj12++ - if yyhl12 { - yyb12 = yyj12 > l + yyj11++ + if yyhl11 { + yyb11 = yyj11 > l } else { - yyb12 = r.CheckBreak() + yyb11 = r.CheckBreak() } - if yyb12 { + if yyb11 { z.DecSendContainerState(codecSelfer_containerArrayEnd1234) return } z.DecSendContainerState(codecSelfer_containerArrayElem1234) if r.TryDecodeAsNil() { - x.APIVersion = "" + if x.Parameters != nil { + x.Parameters = nil + } } else { - yyv15 := &x.APIVersion - yym16 := z.DecBinary() - _ = yym16 + if x.Parameters == nil { + x.Parameters = new(pkg4_runtime.RawExtension) + } + yym15 := z.DecBinary() + _ = yym15 if false { + } else if z.HasExtensions() && z.DecExt(x.Parameters) { + } else if !yym15 && z.IsJSONHandle() { + z.DecJSONUnmarshal(x.Parameters) } else { - *((*string)(yyv15)) = r.DecodeString() + z.DecFallback(x.Parameters, false) } } - yyj12++ - if yyhl12 { - yyb12 = yyj12 > l + yyj11++ + if yyhl11 { + yyb11 = yyj11 > l } else { - yyb12 = r.CheckBreak() + yyb11 = r.CheckBreak() } - if yyb12 { + if yyb11 { z.DecSendContainerState(codecSelfer_containerArrayEnd1234) return } z.DecSendContainerState(codecSelfer_containerArrayElem1234) if r.TryDecodeAsNil() { - x.ListMeta = pkg1_v1.ListMeta{} + x.ParametersChecksum = "" } else { - yyv17 := &x.ListMeta - yym18 := z.DecBinary() - _ = yym18 + yyv16 := &x.ParametersChecksum + yym17 := z.DecBinary() + _ = yym17 if false { - } else if z.HasExtensions() && z.DecExt(yyv17) { } else { - z.DecFallback(yyv17, false) + *((*string)(yyv16)) = r.DecodeString() } } - yyj12++ - if yyhl12 { - yyb12 = yyj12 > l + yyj11++ + if yyhl11 { + yyb11 = yyj11 > l } else { - yyb12 = r.CheckBreak() + yyb11 = r.CheckBreak() } - if yyb12 { + if yyb11 { z.DecSendContainerState(codecSelfer_containerArrayEnd1234) return } z.DecSendContainerState(codecSelfer_containerArrayElem1234) if r.TryDecodeAsNil() { - x.Items = nil + if x.UserInfo != nil { + x.UserInfo = nil + } } else { - yyv19 := &x.Items - yym20 := z.DecBinary() - _ = yym20 - if false { - } else { - h.decSliceServiceInstanceCredential((*[]ServiceInstanceCredential)(yyv19), d) + if x.UserInfo == nil { + x.UserInfo = new(UserInfo) } + x.UserInfo.CodecDecodeSelf(d) } for { - yyj12++ - if yyhl12 { - yyb12 = yyj12 > l + yyj11++ + if yyhl11 { + yyb11 = yyj11 > l } else { - yyb12 = r.CheckBreak() + yyb11 = r.CheckBreak() } - if yyb12 { + if yyb11 { break } z.DecSendContainerState(codecSelfer_containerArrayElem1234) - z.DecStructFieldNotFound(yyj12-1, "") + z.DecStructFieldNotFound(yyj11-1, "") } z.DecSendContainerState(codecSelfer_containerArrayEnd1234) } -func (x *ServiceInstanceCredential) CodecEncodeSelf(e *codec1978.Encoder) { +func (x *ServiceInstanceCredentialList) CodecEncodeSelf(e *codec1978.Encoder) { var h codecSelfer1234 z, r := codec1978.GenHelperEncoder(e) _, _, _ = h, z, r @@ -8642,7 +8764,7 @@ func (x *ServiceInstanceCredential) CodecEncodeSelf(e *codec1978.Encoder) { } else { yysep2 := !z.EncBinary() yy2arr2 := z.EncBasicHandle().StructToArray - var yyq2 [5]bool + var yyq2 [4]bool _, _, _ = yysep2, yyq2, yy2arr2 const yyr2 bool = false yyq2[0] = x.Kind != "" @@ -8650,9 +8772,9 @@ func (x *ServiceInstanceCredential) CodecEncodeSelf(e *codec1978.Encoder) { yyq2[2] = true var yynn2 int if yyr2 || yy2arr2 { - r.EncodeArrayStart(5) + r.EncodeArrayStart(4) } else { - yynn2 = 2 + yynn2 = 1 for _, b := range yyq2 { if b { yynn2++ @@ -8714,7 +8836,7 @@ func (x *ServiceInstanceCredential) CodecEncodeSelf(e *codec1978.Encoder) { if yyr2 || yy2arr2 { z.EncSendContainerState(codecSelfer_containerArrayElem1234) if yyq2[2] { - yy10 := &x.ObjectMeta + yy10 := &x.ListMeta yym11 := z.EncBinary() _ = yym11 if false { @@ -8730,7 +8852,7 @@ func (x *ServiceInstanceCredential) CodecEncodeSelf(e *codec1978.Encoder) { z.EncSendContainerState(codecSelfer_containerMapKey1234) r.EncodeString(codecSelferC_UTF81234, string("metadata")) z.EncSendContainerState(codecSelfer_containerMapValue1234) - yy12 := &x.ObjectMeta + yy12 := &x.ListMeta yym13 := z.EncBinary() _ = yym13 if false { @@ -8742,25 +8864,30 @@ func (x *ServiceInstanceCredential) CodecEncodeSelf(e *codec1978.Encoder) { } if yyr2 || yy2arr2 { z.EncSendContainerState(codecSelfer_containerArrayElem1234) - yy15 := &x.Spec - yy15.CodecEncodeSelf(e) - } else { - z.EncSendContainerState(codecSelfer_containerMapKey1234) - r.EncodeString(codecSelferC_UTF81234, string("spec")) - z.EncSendContainerState(codecSelfer_containerMapValue1234) - yy17 := &x.Spec - yy17.CodecEncodeSelf(e) - } - if yyr2 || yy2arr2 { - z.EncSendContainerState(codecSelfer_containerArrayElem1234) - yy20 := &x.Status - yy20.CodecEncodeSelf(e) + if x.Items == nil { + r.EncodeNil() + } else { + yym15 := z.EncBinary() + _ = yym15 + if false { + } else { + h.encSliceServiceInstanceCredential(([]ServiceInstanceCredential)(x.Items), e) + } + } } else { z.EncSendContainerState(codecSelfer_containerMapKey1234) - r.EncodeString(codecSelferC_UTF81234, string("status")) + r.EncodeString(codecSelferC_UTF81234, string("items")) z.EncSendContainerState(codecSelfer_containerMapValue1234) - yy22 := &x.Status - yy22.CodecEncodeSelf(e) + if x.Items == nil { + r.EncodeNil() + } else { + yym16 := z.EncBinary() + _ = yym16 + if false { + } else { + h.encSliceServiceInstanceCredential(([]ServiceInstanceCredential)(x.Items), e) + } + } } if yyr2 || yy2arr2 { z.EncSendContainerState(codecSelfer_containerArrayEnd1234) @@ -8771,7 +8898,7 @@ func (x *ServiceInstanceCredential) CodecEncodeSelf(e *codec1978.Encoder) { } } -func (x *ServiceInstanceCredential) CodecDecodeSelf(d *codec1978.Decoder) { +func (x *ServiceInstanceCredentialList) CodecDecodeSelf(d *codec1978.Decoder) { var h codecSelfer1234 z, r := codec1978.GenHelperDecoder(d) _, _, _ = h, z, r @@ -8801,7 +8928,7 @@ func (x *ServiceInstanceCredential) CodecDecodeSelf(d *codec1978.Decoder) { } } -func (x *ServiceInstanceCredential) codecDecodeSelfFromMap(l int, d *codec1978.Decoder) { +func (x *ServiceInstanceCredentialList) codecDecodeSelfFromMap(l int, d *codec1978.Decoder) { var h codecSelfer1234 z, r := codec1978.GenHelperDecoder(d) _, _, _ = h, z, r @@ -8849,9 +8976,9 @@ func (x *ServiceInstanceCredential) codecDecodeSelfFromMap(l int, d *codec1978.D } case "metadata": if r.TryDecodeAsNil() { - x.ObjectMeta = pkg1_v1.ObjectMeta{} + x.ListMeta = pkg1_v1.ListMeta{} } else { - yyv8 := &x.ObjectMeta + yyv8 := &x.ListMeta yym9 := z.DecBinary() _ = yym9 if false { @@ -8860,19 +8987,17 @@ func (x *ServiceInstanceCredential) codecDecodeSelfFromMap(l int, d *codec1978.D z.DecFallback(yyv8, false) } } - case "spec": - if r.TryDecodeAsNil() { - x.Spec = ServiceInstanceCredentialSpec{} - } else { - yyv10 := &x.Spec - yyv10.CodecDecodeSelf(d) - } - case "status": + case "items": if r.TryDecodeAsNil() { - x.Status = ServiceInstanceCredentialStatus{} + x.Items = nil } else { - yyv11 := &x.Status - yyv11.CodecDecodeSelf(d) + yyv10 := &x.Items + yym11 := z.DecBinary() + _ = yym11 + if false { + } else { + h.decSliceServiceInstanceCredential((*[]ServiceInstanceCredential)(yyv10), d) + } } default: z.DecStructFieldNotFound(-1, yys3) @@ -8881,7 +9006,7 @@ func (x *ServiceInstanceCredential) codecDecodeSelfFromMap(l int, d *codec1978.D z.DecSendContainerState(codecSelfer_containerMapEnd1234) } -func (x *ServiceInstanceCredential) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) { +func (x *ServiceInstanceCredentialList) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) { var h codecSelfer1234 z, r := codec1978.GenHelperDecoder(d) _, _, _ = h, z, r @@ -8944,9 +9069,9 @@ func (x *ServiceInstanceCredential) codecDecodeSelfFromArray(l int, d *codec1978 } z.DecSendContainerState(codecSelfer_containerArrayElem1234) if r.TryDecodeAsNil() { - x.ObjectMeta = pkg1_v1.ObjectMeta{} + x.ListMeta = pkg1_v1.ListMeta{} } else { - yyv17 := &x.ObjectMeta + yyv17 := &x.ListMeta yym18 := z.DecBinary() _ = yym18 if false { @@ -8967,27 +9092,15 @@ func (x *ServiceInstanceCredential) codecDecodeSelfFromArray(l int, d *codec1978 } z.DecSendContainerState(codecSelfer_containerArrayElem1234) if r.TryDecodeAsNil() { - x.Spec = ServiceInstanceCredentialSpec{} - } else { - yyv19 := &x.Spec - yyv19.CodecDecodeSelf(d) - } - yyj12++ - if yyhl12 { - yyb12 = yyj12 > l - } else { - yyb12 = r.CheckBreak() - } - if yyb12 { - z.DecSendContainerState(codecSelfer_containerArrayEnd1234) - return - } - z.DecSendContainerState(codecSelfer_containerArrayElem1234) - if r.TryDecodeAsNil() { - x.Status = ServiceInstanceCredentialStatus{} + x.Items = nil } else { - yyv20 := &x.Status - yyv20.CodecDecodeSelf(d) + yyv19 := &x.Items + yym20 := z.DecBinary() + _ = yym20 + if false { + } else { + h.decSliceServiceInstanceCredential((*[]ServiceInstanceCredential)(yyv19), d) + } } for { yyj12++ @@ -9005,7 +9118,7 @@ func (x *ServiceInstanceCredential) codecDecodeSelfFromArray(l int, d *codec1978 z.DecSendContainerState(codecSelfer_containerArrayEnd1234) } -func (x *ServiceInstanceCredentialSpec) CodecEncodeSelf(e *codec1978.Encoder) { +func (x *ServiceInstanceCredential) CodecEncodeSelf(e *codec1978.Encoder) { var h codecSelfer1234 z, r := codec1978.GenHelperEncoder(e) _, _, _ = h, z, r @@ -9019,17 +9132,17 @@ func (x *ServiceInstanceCredentialSpec) CodecEncodeSelf(e *codec1978.Encoder) { } else { yysep2 := !z.EncBinary() yy2arr2 := z.EncBasicHandle().StructToArray - var yyq2 [6]bool + var yyq2 [5]bool _, _, _ = yysep2, yyq2, yy2arr2 const yyr2 bool = false - yyq2[1] = x.Parameters != nil - yyq2[2] = len(x.ParametersFrom) != 0 - yyq2[3] = x.SecretName != "" + yyq2[0] = x.Kind != "" + yyq2[1] = x.APIVersion != "" + yyq2[2] = true var yynn2 int if yyr2 || yy2arr2 { - r.EncodeArrayStart(6) + r.EncodeArrayStart(5) } else { - yynn2 = 3 + yynn2 = 2 for _, b := range yyq2 { if b { yynn2++ @@ -9040,147 +9153,104 @@ func (x *ServiceInstanceCredentialSpec) CodecEncodeSelf(e *codec1978.Encoder) { } if yyr2 || yy2arr2 { z.EncSendContainerState(codecSelfer_containerArrayElem1234) - yy4 := &x.ServiceInstanceRef - yy4.CodecEncodeSelf(e) - } else { - z.EncSendContainerState(codecSelfer_containerMapKey1234) - r.EncodeString(codecSelferC_UTF81234, string("instanceRef")) - z.EncSendContainerState(codecSelfer_containerMapValue1234) - yy6 := &x.ServiceInstanceRef - yy6.CodecEncodeSelf(e) - } - if yyr2 || yy2arr2 { - z.EncSendContainerState(codecSelfer_containerArrayElem1234) - if yyq2[1] { - if x.Parameters == nil { - r.EncodeNil() + if yyq2[0] { + yym4 := z.EncBinary() + _ = yym4 + if false { } else { - yym9 := z.EncBinary() - _ = yym9 - if false { - } else if z.HasExtensions() && z.EncExt(x.Parameters) { - } else if !yym9 && z.IsJSONHandle() { - z.EncJSONMarshal(x.Parameters) - } else { - z.EncFallback(x.Parameters) - } + r.EncodeString(codecSelferC_UTF81234, string(x.Kind)) } } else { - r.EncodeNil() + r.EncodeString(codecSelferC_UTF81234, "") } } else { - if yyq2[1] { + if yyq2[0] { z.EncSendContainerState(codecSelfer_containerMapKey1234) - r.EncodeString(codecSelferC_UTF81234, string("parameters")) + r.EncodeString(codecSelferC_UTF81234, string("kind")) z.EncSendContainerState(codecSelfer_containerMapValue1234) - if x.Parameters == nil { - r.EncodeNil() - } else { - yym10 := z.EncBinary() - _ = yym10 - if false { - } else if z.HasExtensions() && z.EncExt(x.Parameters) { - } else if !yym10 && z.IsJSONHandle() { - z.EncJSONMarshal(x.Parameters) - } else { - z.EncFallback(x.Parameters) - } + yym5 := z.EncBinary() + _ = yym5 + if false { + } else { + r.EncodeString(codecSelferC_UTF81234, string(x.Kind)) } } } if yyr2 || yy2arr2 { z.EncSendContainerState(codecSelfer_containerArrayElem1234) - if yyq2[2] { - if x.ParametersFrom == nil { - r.EncodeNil() + if yyq2[1] { + yym7 := z.EncBinary() + _ = yym7 + if false { } else { - yym12 := z.EncBinary() - _ = yym12 - if false { - } else { - h.encSliceParametersFromSource(([]ParametersFromSource)(x.ParametersFrom), e) - } + r.EncodeString(codecSelferC_UTF81234, string(x.APIVersion)) } } else { - r.EncodeNil() + r.EncodeString(codecSelferC_UTF81234, "") } } else { - if yyq2[2] { + if yyq2[1] { z.EncSendContainerState(codecSelfer_containerMapKey1234) - r.EncodeString(codecSelferC_UTF81234, string("parametersFrom")) + r.EncodeString(codecSelferC_UTF81234, string("apiVersion")) z.EncSendContainerState(codecSelfer_containerMapValue1234) - if x.ParametersFrom == nil { - r.EncodeNil() + yym8 := z.EncBinary() + _ = yym8 + if false { } else { - yym13 := z.EncBinary() - _ = yym13 - if false { - } else { - h.encSliceParametersFromSource(([]ParametersFromSource)(x.ParametersFrom), e) - } + r.EncodeString(codecSelferC_UTF81234, string(x.APIVersion)) } } } if yyr2 || yy2arr2 { z.EncSendContainerState(codecSelfer_containerArrayElem1234) - if yyq2[3] { - yym15 := z.EncBinary() - _ = yym15 + if yyq2[2] { + yy10 := &x.ObjectMeta + yym11 := z.EncBinary() + _ = yym11 if false { + } else if z.HasExtensions() && z.EncExt(yy10) { } else { - r.EncodeString(codecSelferC_UTF81234, string(x.SecretName)) + z.EncFallback(yy10) } } else { - r.EncodeString(codecSelferC_UTF81234, "") + r.EncodeNil() } } else { - if yyq2[3] { + if yyq2[2] { z.EncSendContainerState(codecSelfer_containerMapKey1234) - r.EncodeString(codecSelferC_UTF81234, string("secretName")) + r.EncodeString(codecSelferC_UTF81234, string("metadata")) z.EncSendContainerState(codecSelfer_containerMapValue1234) - yym16 := z.EncBinary() - _ = yym16 + yy12 := &x.ObjectMeta + yym13 := z.EncBinary() + _ = yym13 if false { + } else if z.HasExtensions() && z.EncExt(yy12) { } else { - r.EncodeString(codecSelferC_UTF81234, string(x.SecretName)) + z.EncFallback(yy12) } } } if yyr2 || yy2arr2 { z.EncSendContainerState(codecSelfer_containerArrayElem1234) - yym18 := z.EncBinary() - _ = yym18 - if false { - } else { - r.EncodeString(codecSelferC_UTF81234, string(x.ExternalID)) - } + yy15 := &x.Spec + yy15.CodecEncodeSelf(e) } else { z.EncSendContainerState(codecSelfer_containerMapKey1234) - r.EncodeString(codecSelferC_UTF81234, string("externalID")) + r.EncodeString(codecSelferC_UTF81234, string("spec")) z.EncSendContainerState(codecSelfer_containerMapValue1234) - yym19 := z.EncBinary() - _ = yym19 - if false { - } else { - r.EncodeString(codecSelferC_UTF81234, string(x.ExternalID)) - } + yy17 := &x.Spec + yy17.CodecEncodeSelf(e) } if yyr2 || yy2arr2 { z.EncSendContainerState(codecSelfer_containerArrayElem1234) - if x.UserInfo == nil { - r.EncodeNil() - } else { - x.UserInfo.CodecEncodeSelf(e) - } + yy20 := &x.Status + yy20.CodecEncodeSelf(e) } else { z.EncSendContainerState(codecSelfer_containerMapKey1234) - r.EncodeString(codecSelferC_UTF81234, string("userInfo")) + r.EncodeString(codecSelferC_UTF81234, string("status")) z.EncSendContainerState(codecSelfer_containerMapValue1234) - if x.UserInfo == nil { - r.EncodeNil() - } else { - x.UserInfo.CodecEncodeSelf(e) - } + yy22 := &x.Status + yy22.CodecEncodeSelf(e) } if yyr2 || yy2arr2 { z.EncSendContainerState(codecSelfer_containerArrayEnd1234) @@ -9191,7 +9261,7 @@ func (x *ServiceInstanceCredentialSpec) CodecEncodeSelf(e *codec1978.Encoder) { } } -func (x *ServiceInstanceCredentialSpec) CodecDecodeSelf(d *codec1978.Decoder) { +func (x *ServiceInstanceCredential) CodecDecodeSelf(d *codec1978.Decoder) { var h codecSelfer1234 z, r := codec1978.GenHelperDecoder(d) _, _, _ = h, z, r @@ -9221,7 +9291,7 @@ func (x *ServiceInstanceCredentialSpec) CodecDecodeSelf(d *codec1978.Decoder) { } } -func (x *ServiceInstanceCredentialSpec) codecDecodeSelfFromMap(l int, d *codec1978.Decoder) { +func (x *ServiceInstanceCredential) codecDecodeSelfFromMap(l int, d *codec1978.Decoder) { var h codecSelfer1234 z, r := codec1978.GenHelperDecoder(d) _, _, _ = h, z, r @@ -9243,78 +9313,56 @@ func (x *ServiceInstanceCredentialSpec) codecDecodeSelfFromMap(l int, d *codec19 yys3 := string(yys3Slc) z.DecSendContainerState(codecSelfer_containerMapValue1234) switch yys3 { - case "instanceRef": - if r.TryDecodeAsNil() { - x.ServiceInstanceRef = pkg3_v1.LocalObjectReference{} - } else { - yyv4 := &x.ServiceInstanceRef - yyv4.CodecDecodeSelf(d) - } - case "parameters": + case "kind": if r.TryDecodeAsNil() { - if x.Parameters != nil { - x.Parameters = nil - } + x.Kind = "" } else { - if x.Parameters == nil { - x.Parameters = new(pkg4_runtime.RawExtension) - } - yym6 := z.DecBinary() - _ = yym6 + yyv4 := &x.Kind + yym5 := z.DecBinary() + _ = yym5 if false { - } else if z.HasExtensions() && z.DecExt(x.Parameters) { - } else if !yym6 && z.IsJSONHandle() { - z.DecJSONUnmarshal(x.Parameters) } else { - z.DecFallback(x.Parameters, false) + *((*string)(yyv4)) = r.DecodeString() } } - case "parametersFrom": + case "apiVersion": if r.TryDecodeAsNil() { - x.ParametersFrom = nil + x.APIVersion = "" } else { - yyv7 := &x.ParametersFrom - yym8 := z.DecBinary() - _ = yym8 + yyv6 := &x.APIVersion + yym7 := z.DecBinary() + _ = yym7 if false { } else { - h.decSliceParametersFromSource((*[]ParametersFromSource)(yyv7), d) + *((*string)(yyv6)) = r.DecodeString() } } - case "secretName": + case "metadata": if r.TryDecodeAsNil() { - x.SecretName = "" + x.ObjectMeta = pkg1_v1.ObjectMeta{} } else { - yyv9 := &x.SecretName - yym10 := z.DecBinary() - _ = yym10 + yyv8 := &x.ObjectMeta + yym9 := z.DecBinary() + _ = yym9 if false { + } else if z.HasExtensions() && z.DecExt(yyv8) { } else { - *((*string)(yyv9)) = r.DecodeString() + z.DecFallback(yyv8, false) } } - case "externalID": + case "spec": if r.TryDecodeAsNil() { - x.ExternalID = "" + x.Spec = ServiceInstanceCredentialSpec{} } else { - yyv11 := &x.ExternalID - yym12 := z.DecBinary() - _ = yym12 - if false { - } else { - *((*string)(yyv11)) = r.DecodeString() - } + yyv10 := &x.Spec + yyv10.CodecDecodeSelf(d) } - case "userInfo": + case "status": if r.TryDecodeAsNil() { - if x.UserInfo != nil { - x.UserInfo = nil - } + x.Status = ServiceInstanceCredentialStatus{} } else { - if x.UserInfo == nil { - x.UserInfo = new(UserInfo) - } - x.UserInfo.CodecDecodeSelf(d) + yyv11 := &x.Status + yyv11.CodecDecodeSelf(d) } default: z.DecStructFieldNotFound(-1, yys3) @@ -9323,163 +9371,1088 @@ func (x *ServiceInstanceCredentialSpec) codecDecodeSelfFromMap(l int, d *codec19 z.DecSendContainerState(codecSelfer_containerMapEnd1234) } -func (x *ServiceInstanceCredentialSpec) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) { +func (x *ServiceInstanceCredential) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) { var h codecSelfer1234 z, r := codec1978.GenHelperDecoder(d) _, _, _ = h, z, r - var yyj14 int - var yyb14 bool - var yyhl14 bool = l >= 0 - yyj14++ - if yyhl14 { - yyb14 = yyj14 > l + var yyj12 int + var yyb12 bool + var yyhl12 bool = l >= 0 + yyj12++ + if yyhl12 { + yyb12 = yyj12 > l } else { - yyb14 = r.CheckBreak() + yyb12 = r.CheckBreak() } - if yyb14 { + if yyb12 { z.DecSendContainerState(codecSelfer_containerArrayEnd1234) return } z.DecSendContainerState(codecSelfer_containerArrayElem1234) if r.TryDecodeAsNil() { - x.ServiceInstanceRef = pkg3_v1.LocalObjectReference{} + x.Kind = "" } else { - yyv15 := &x.ServiceInstanceRef - yyv15.CodecDecodeSelf(d) + yyv13 := &x.Kind + yym14 := z.DecBinary() + _ = yym14 + if false { + } else { + *((*string)(yyv13)) = r.DecodeString() + } } - yyj14++ - if yyhl14 { - yyb14 = yyj14 > l + yyj12++ + if yyhl12 { + yyb12 = yyj12 > l } else { - yyb14 = r.CheckBreak() + yyb12 = r.CheckBreak() } - if yyb14 { + if yyb12 { z.DecSendContainerState(codecSelfer_containerArrayEnd1234) return } z.DecSendContainerState(codecSelfer_containerArrayElem1234) if r.TryDecodeAsNil() { - if x.Parameters != nil { - x.Parameters = nil - } + x.APIVersion = "" } else { - if x.Parameters == nil { - x.Parameters = new(pkg4_runtime.RawExtension) - } - yym17 := z.DecBinary() - _ = yym17 + yyv15 := &x.APIVersion + yym16 := z.DecBinary() + _ = yym16 if false { - } else if z.HasExtensions() && z.DecExt(x.Parameters) { - } else if !yym17 && z.IsJSONHandle() { - z.DecJSONUnmarshal(x.Parameters) } else { - z.DecFallback(x.Parameters, false) + *((*string)(yyv15)) = r.DecodeString() } } - yyj14++ - if yyhl14 { - yyb14 = yyj14 > l + yyj12++ + if yyhl12 { + yyb12 = yyj12 > l } else { - yyb14 = r.CheckBreak() + yyb12 = r.CheckBreak() } - if yyb14 { + if yyb12 { z.DecSendContainerState(codecSelfer_containerArrayEnd1234) return } z.DecSendContainerState(codecSelfer_containerArrayElem1234) if r.TryDecodeAsNil() { - x.ParametersFrom = nil + x.ObjectMeta = pkg1_v1.ObjectMeta{} } else { - yyv18 := &x.ParametersFrom - yym19 := z.DecBinary() - _ = yym19 - if false { - } else { + yyv17 := &x.ObjectMeta + yym18 := z.DecBinary() + _ = yym18 + if false { + } else if z.HasExtensions() && z.DecExt(yyv17) { + } else { + z.DecFallback(yyv17, false) + } + } + yyj12++ + if yyhl12 { + yyb12 = yyj12 > l + } else { + yyb12 = r.CheckBreak() + } + if yyb12 { + z.DecSendContainerState(codecSelfer_containerArrayEnd1234) + return + } + z.DecSendContainerState(codecSelfer_containerArrayElem1234) + if r.TryDecodeAsNil() { + x.Spec = ServiceInstanceCredentialSpec{} + } else { + yyv19 := &x.Spec + yyv19.CodecDecodeSelf(d) + } + yyj12++ + if yyhl12 { + yyb12 = yyj12 > l + } else { + yyb12 = r.CheckBreak() + } + if yyb12 { + z.DecSendContainerState(codecSelfer_containerArrayEnd1234) + return + } + z.DecSendContainerState(codecSelfer_containerArrayElem1234) + if r.TryDecodeAsNil() { + x.Status = ServiceInstanceCredentialStatus{} + } else { + yyv20 := &x.Status + yyv20.CodecDecodeSelf(d) + } + for { + yyj12++ + if yyhl12 { + yyb12 = yyj12 > l + } else { + yyb12 = r.CheckBreak() + } + if yyb12 { + break + } + z.DecSendContainerState(codecSelfer_containerArrayElem1234) + z.DecStructFieldNotFound(yyj12-1, "") + } + z.DecSendContainerState(codecSelfer_containerArrayEnd1234) +} + +func (x *ServiceInstanceCredentialSpec) CodecEncodeSelf(e *codec1978.Encoder) { + var h codecSelfer1234 + z, r := codec1978.GenHelperEncoder(e) + _, _, _ = h, z, r + if x == nil { + r.EncodeNil() + } else { + yym1 := z.EncBinary() + _ = yym1 + if false { + } else if z.HasExtensions() && z.EncExt(x) { + } else { + yysep2 := !z.EncBinary() + yy2arr2 := z.EncBasicHandle().StructToArray + var yyq2 [6]bool + _, _, _ = yysep2, yyq2, yy2arr2 + const yyr2 bool = false + yyq2[1] = x.Parameters != nil + yyq2[2] = len(x.ParametersFrom) != 0 + yyq2[3] = x.SecretName != "" + var yynn2 int + if yyr2 || yy2arr2 { + r.EncodeArrayStart(6) + } else { + yynn2 = 3 + for _, b := range yyq2 { + if b { + yynn2++ + } + } + r.EncodeMapStart(yynn2) + yynn2 = 0 + } + if yyr2 || yy2arr2 { + z.EncSendContainerState(codecSelfer_containerArrayElem1234) + yy4 := &x.ServiceInstanceRef + yy4.CodecEncodeSelf(e) + } else { + z.EncSendContainerState(codecSelfer_containerMapKey1234) + r.EncodeString(codecSelferC_UTF81234, string("instanceRef")) + z.EncSendContainerState(codecSelfer_containerMapValue1234) + yy6 := &x.ServiceInstanceRef + yy6.CodecEncodeSelf(e) + } + if yyr2 || yy2arr2 { + z.EncSendContainerState(codecSelfer_containerArrayElem1234) + if yyq2[1] { + if x.Parameters == nil { + r.EncodeNil() + } else { + yym9 := z.EncBinary() + _ = yym9 + if false { + } else if z.HasExtensions() && z.EncExt(x.Parameters) { + } else if !yym9 && z.IsJSONHandle() { + z.EncJSONMarshal(x.Parameters) + } else { + z.EncFallback(x.Parameters) + } + } + } else { + r.EncodeNil() + } + } else { + if yyq2[1] { + z.EncSendContainerState(codecSelfer_containerMapKey1234) + r.EncodeString(codecSelferC_UTF81234, string("parameters")) + z.EncSendContainerState(codecSelfer_containerMapValue1234) + if x.Parameters == nil { + r.EncodeNil() + } else { + yym10 := z.EncBinary() + _ = yym10 + if false { + } else if z.HasExtensions() && z.EncExt(x.Parameters) { + } else if !yym10 && z.IsJSONHandle() { + z.EncJSONMarshal(x.Parameters) + } else { + z.EncFallback(x.Parameters) + } + } + } + } + if yyr2 || yy2arr2 { + z.EncSendContainerState(codecSelfer_containerArrayElem1234) + if yyq2[2] { + if x.ParametersFrom == nil { + r.EncodeNil() + } else { + yym12 := z.EncBinary() + _ = yym12 + if false { + } else { + h.encSliceParametersFromSource(([]ParametersFromSource)(x.ParametersFrom), e) + } + } + } else { + r.EncodeNil() + } + } else { + if yyq2[2] { + z.EncSendContainerState(codecSelfer_containerMapKey1234) + r.EncodeString(codecSelferC_UTF81234, string("parametersFrom")) + z.EncSendContainerState(codecSelfer_containerMapValue1234) + if x.ParametersFrom == nil { + r.EncodeNil() + } else { + yym13 := z.EncBinary() + _ = yym13 + if false { + } else { + h.encSliceParametersFromSource(([]ParametersFromSource)(x.ParametersFrom), e) + } + } + } + } + if yyr2 || yy2arr2 { + z.EncSendContainerState(codecSelfer_containerArrayElem1234) + if yyq2[3] { + yym15 := z.EncBinary() + _ = yym15 + if false { + } else { + r.EncodeString(codecSelferC_UTF81234, string(x.SecretName)) + } + } else { + r.EncodeString(codecSelferC_UTF81234, "") + } + } else { + if yyq2[3] { + z.EncSendContainerState(codecSelfer_containerMapKey1234) + r.EncodeString(codecSelferC_UTF81234, string("secretName")) + z.EncSendContainerState(codecSelfer_containerMapValue1234) + yym16 := z.EncBinary() + _ = yym16 + if false { + } else { + r.EncodeString(codecSelferC_UTF81234, string(x.SecretName)) + } + } + } + if yyr2 || yy2arr2 { + z.EncSendContainerState(codecSelfer_containerArrayElem1234) + yym18 := z.EncBinary() + _ = yym18 + if false { + } else { + r.EncodeString(codecSelferC_UTF81234, string(x.ExternalID)) + } + } else { + z.EncSendContainerState(codecSelfer_containerMapKey1234) + r.EncodeString(codecSelferC_UTF81234, string("externalID")) + z.EncSendContainerState(codecSelfer_containerMapValue1234) + yym19 := z.EncBinary() + _ = yym19 + if false { + } else { + r.EncodeString(codecSelferC_UTF81234, string(x.ExternalID)) + } + } + if yyr2 || yy2arr2 { + z.EncSendContainerState(codecSelfer_containerArrayElem1234) + if x.UserInfo == nil { + r.EncodeNil() + } else { + x.UserInfo.CodecEncodeSelf(e) + } + } else { + z.EncSendContainerState(codecSelfer_containerMapKey1234) + r.EncodeString(codecSelferC_UTF81234, string("userInfo")) + z.EncSendContainerState(codecSelfer_containerMapValue1234) + if x.UserInfo == nil { + r.EncodeNil() + } else { + x.UserInfo.CodecEncodeSelf(e) + } + } + if yyr2 || yy2arr2 { + z.EncSendContainerState(codecSelfer_containerArrayEnd1234) + } else { + z.EncSendContainerState(codecSelfer_containerMapEnd1234) + } + } + } +} + +func (x *ServiceInstanceCredentialSpec) CodecDecodeSelf(d *codec1978.Decoder) { + var h codecSelfer1234 + z, r := codec1978.GenHelperDecoder(d) + _, _, _ = h, z, r + yym1 := z.DecBinary() + _ = yym1 + if false { + } else if z.HasExtensions() && z.DecExt(x) { + } else { + yyct2 := r.ContainerType() + if yyct2 == codecSelferValueTypeMap1234 { + yyl2 := r.ReadMapStart() + if yyl2 == 0 { + z.DecSendContainerState(codecSelfer_containerMapEnd1234) + } else { + x.codecDecodeSelfFromMap(yyl2, d) + } + } else if yyct2 == codecSelferValueTypeArray1234 { + yyl2 := r.ReadArrayStart() + if yyl2 == 0 { + z.DecSendContainerState(codecSelfer_containerArrayEnd1234) + } else { + x.codecDecodeSelfFromArray(yyl2, d) + } + } else { + panic(codecSelferOnlyMapOrArrayEncodeToStructErr1234) + } + } +} + +func (x *ServiceInstanceCredentialSpec) codecDecodeSelfFromMap(l int, d *codec1978.Decoder) { + var h codecSelfer1234 + z, r := codec1978.GenHelperDecoder(d) + _, _, _ = h, z, r + var yys3Slc = z.DecScratchBuffer() // default slice to decode into + _ = yys3Slc + var yyhl3 bool = l >= 0 + for yyj3 := 0; ; yyj3++ { + if yyhl3 { + if yyj3 >= l { + break + } + } else { + if r.CheckBreak() { + break + } + } + z.DecSendContainerState(codecSelfer_containerMapKey1234) + yys3Slc = r.DecodeBytes(yys3Slc, true, true) + yys3 := string(yys3Slc) + z.DecSendContainerState(codecSelfer_containerMapValue1234) + switch yys3 { + case "instanceRef": + if r.TryDecodeAsNil() { + x.ServiceInstanceRef = pkg3_v1.LocalObjectReference{} + } else { + yyv4 := &x.ServiceInstanceRef + yyv4.CodecDecodeSelf(d) + } + case "parameters": + if r.TryDecodeAsNil() { + if x.Parameters != nil { + x.Parameters = nil + } + } else { + if x.Parameters == nil { + x.Parameters = new(pkg4_runtime.RawExtension) + } + yym6 := z.DecBinary() + _ = yym6 + if false { + } else if z.HasExtensions() && z.DecExt(x.Parameters) { + } else if !yym6 && z.IsJSONHandle() { + z.DecJSONUnmarshal(x.Parameters) + } else { + z.DecFallback(x.Parameters, false) + } + } + case "parametersFrom": + if r.TryDecodeAsNil() { + x.ParametersFrom = nil + } else { + yyv7 := &x.ParametersFrom + yym8 := z.DecBinary() + _ = yym8 + if false { + } else { + h.decSliceParametersFromSource((*[]ParametersFromSource)(yyv7), d) + } + } + case "secretName": + if r.TryDecodeAsNil() { + x.SecretName = "" + } else { + yyv9 := &x.SecretName + yym10 := z.DecBinary() + _ = yym10 + if false { + } else { + *((*string)(yyv9)) = r.DecodeString() + } + } + case "externalID": + if r.TryDecodeAsNil() { + x.ExternalID = "" + } else { + yyv11 := &x.ExternalID + yym12 := z.DecBinary() + _ = yym12 + if false { + } else { + *((*string)(yyv11)) = r.DecodeString() + } + } + case "userInfo": + if r.TryDecodeAsNil() { + if x.UserInfo != nil { + x.UserInfo = nil + } + } else { + if x.UserInfo == nil { + x.UserInfo = new(UserInfo) + } + x.UserInfo.CodecDecodeSelf(d) + } + default: + z.DecStructFieldNotFound(-1, yys3) + } // end switch yys3 + } // end for yyj3 + z.DecSendContainerState(codecSelfer_containerMapEnd1234) +} + +func (x *ServiceInstanceCredentialSpec) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) { + var h codecSelfer1234 + z, r := codec1978.GenHelperDecoder(d) + _, _, _ = h, z, r + var yyj14 int + var yyb14 bool + var yyhl14 bool = l >= 0 + yyj14++ + if yyhl14 { + yyb14 = yyj14 > l + } else { + yyb14 = r.CheckBreak() + } + if yyb14 { + z.DecSendContainerState(codecSelfer_containerArrayEnd1234) + return + } + z.DecSendContainerState(codecSelfer_containerArrayElem1234) + if r.TryDecodeAsNil() { + x.ServiceInstanceRef = pkg3_v1.LocalObjectReference{} + } else { + yyv15 := &x.ServiceInstanceRef + yyv15.CodecDecodeSelf(d) + } + yyj14++ + if yyhl14 { + yyb14 = yyj14 > l + } else { + yyb14 = r.CheckBreak() + } + if yyb14 { + z.DecSendContainerState(codecSelfer_containerArrayEnd1234) + return + } + z.DecSendContainerState(codecSelfer_containerArrayElem1234) + if r.TryDecodeAsNil() { + if x.Parameters != nil { + x.Parameters = nil + } + } else { + if x.Parameters == nil { + x.Parameters = new(pkg4_runtime.RawExtension) + } + yym17 := z.DecBinary() + _ = yym17 + if false { + } else if z.HasExtensions() && z.DecExt(x.Parameters) { + } else if !yym17 && z.IsJSONHandle() { + z.DecJSONUnmarshal(x.Parameters) + } else { + z.DecFallback(x.Parameters, false) + } + } + yyj14++ + if yyhl14 { + yyb14 = yyj14 > l + } else { + yyb14 = r.CheckBreak() + } + if yyb14 { + z.DecSendContainerState(codecSelfer_containerArrayEnd1234) + return + } + z.DecSendContainerState(codecSelfer_containerArrayElem1234) + if r.TryDecodeAsNil() { + x.ParametersFrom = nil + } else { + yyv18 := &x.ParametersFrom + yym19 := z.DecBinary() + _ = yym19 + if false { + } else { h.decSliceParametersFromSource((*[]ParametersFromSource)(yyv18), d) } } - yyj14++ - if yyhl14 { - yyb14 = yyj14 > l + yyj14++ + if yyhl14 { + yyb14 = yyj14 > l + } else { + yyb14 = r.CheckBreak() + } + if yyb14 { + z.DecSendContainerState(codecSelfer_containerArrayEnd1234) + return + } + z.DecSendContainerState(codecSelfer_containerArrayElem1234) + if r.TryDecodeAsNil() { + x.SecretName = "" + } else { + yyv20 := &x.SecretName + yym21 := z.DecBinary() + _ = yym21 + if false { + } else { + *((*string)(yyv20)) = r.DecodeString() + } + } + yyj14++ + if yyhl14 { + yyb14 = yyj14 > l + } else { + yyb14 = r.CheckBreak() + } + if yyb14 { + z.DecSendContainerState(codecSelfer_containerArrayEnd1234) + return + } + z.DecSendContainerState(codecSelfer_containerArrayElem1234) + if r.TryDecodeAsNil() { + x.ExternalID = "" + } else { + yyv22 := &x.ExternalID + yym23 := z.DecBinary() + _ = yym23 + if false { + } else { + *((*string)(yyv22)) = r.DecodeString() + } + } + yyj14++ + if yyhl14 { + yyb14 = yyj14 > l + } else { + yyb14 = r.CheckBreak() + } + if yyb14 { + z.DecSendContainerState(codecSelfer_containerArrayEnd1234) + return + } + z.DecSendContainerState(codecSelfer_containerArrayElem1234) + if r.TryDecodeAsNil() { + if x.UserInfo != nil { + x.UserInfo = nil + } + } else { + if x.UserInfo == nil { + x.UserInfo = new(UserInfo) + } + x.UserInfo.CodecDecodeSelf(d) + } + for { + yyj14++ + if yyhl14 { + yyb14 = yyj14 > l + } else { + yyb14 = r.CheckBreak() + } + if yyb14 { + break + } + z.DecSendContainerState(codecSelfer_containerArrayElem1234) + z.DecStructFieldNotFound(yyj14-1, "") + } + z.DecSendContainerState(codecSelfer_containerArrayEnd1234) +} + +func (x *ServiceInstanceCredentialStatus) CodecEncodeSelf(e *codec1978.Encoder) { + var h codecSelfer1234 + z, r := codec1978.GenHelperEncoder(e) + _, _, _ = h, z, r + if x == nil { + r.EncodeNil() + } else { + yym1 := z.EncBinary() + _ = yym1 + if false { + } else if z.HasExtensions() && z.EncExt(x) { + } else { + yysep2 := !z.EncBinary() + yy2arr2 := z.EncBasicHandle().StructToArray + var yyq2 [6]bool + _, _, _ = yysep2, yyq2, yy2arr2 + const yyr2 bool = false + yyq2[1] = x.CurrentOperation != "" + yyq2[3] = x.OperationStartTime != nil + yyq2[4] = x.InProgressProperties != nil + yyq2[5] = x.ExternalProperties != nil + var yynn2 int + if yyr2 || yy2arr2 { + r.EncodeArrayStart(6) + } else { + yynn2 = 2 + for _, b := range yyq2 { + if b { + yynn2++ + } + } + r.EncodeMapStart(yynn2) + yynn2 = 0 + } + if yyr2 || yy2arr2 { + z.EncSendContainerState(codecSelfer_containerArrayElem1234) + if x.Conditions == nil { + r.EncodeNil() + } else { + yym4 := z.EncBinary() + _ = yym4 + if false { + } else { + h.encSliceServiceInstanceCredentialCondition(([]ServiceInstanceCredentialCondition)(x.Conditions), e) + } + } + } else { + z.EncSendContainerState(codecSelfer_containerMapKey1234) + r.EncodeString(codecSelferC_UTF81234, string("conditions")) + z.EncSendContainerState(codecSelfer_containerMapValue1234) + if x.Conditions == nil { + r.EncodeNil() + } else { + yym5 := z.EncBinary() + _ = yym5 + if false { + } else { + h.encSliceServiceInstanceCredentialCondition(([]ServiceInstanceCredentialCondition)(x.Conditions), e) + } + } + } + if yyr2 || yy2arr2 { + z.EncSendContainerState(codecSelfer_containerArrayElem1234) + if yyq2[1] { + x.CurrentOperation.CodecEncodeSelf(e) + } else { + r.EncodeString(codecSelferC_UTF81234, "") + } + } else { + if yyq2[1] { + z.EncSendContainerState(codecSelfer_containerMapKey1234) + r.EncodeString(codecSelferC_UTF81234, string("currentOperation")) + z.EncSendContainerState(codecSelfer_containerMapValue1234) + x.CurrentOperation.CodecEncodeSelf(e) + } + } + if yyr2 || yy2arr2 { + z.EncSendContainerState(codecSelfer_containerArrayElem1234) + yym10 := z.EncBinary() + _ = yym10 + if false { + } else { + r.EncodeInt(int64(x.ReconciledGeneration)) + } + } else { + z.EncSendContainerState(codecSelfer_containerMapKey1234) + r.EncodeString(codecSelferC_UTF81234, string("reconciledGeneration")) + z.EncSendContainerState(codecSelfer_containerMapValue1234) + yym11 := z.EncBinary() + _ = yym11 + if false { + } else { + r.EncodeInt(int64(x.ReconciledGeneration)) + } + } + if yyr2 || yy2arr2 { + z.EncSendContainerState(codecSelfer_containerArrayElem1234) + if yyq2[3] { + if x.OperationStartTime == nil { + r.EncodeNil() + } else { + yym13 := z.EncBinary() + _ = yym13 + if false { + } else if z.HasExtensions() && z.EncExt(x.OperationStartTime) { + } else if yym13 { + z.EncBinaryMarshal(x.OperationStartTime) + } else if !yym13 && z.IsJSONHandle() { + z.EncJSONMarshal(x.OperationStartTime) + } else { + z.EncFallback(x.OperationStartTime) + } + } + } else { + r.EncodeNil() + } + } else { + if yyq2[3] { + z.EncSendContainerState(codecSelfer_containerMapKey1234) + r.EncodeString(codecSelferC_UTF81234, string("operationStartTime")) + z.EncSendContainerState(codecSelfer_containerMapValue1234) + if x.OperationStartTime == nil { + r.EncodeNil() + } else { + yym14 := z.EncBinary() + _ = yym14 + if false { + } else if z.HasExtensions() && z.EncExt(x.OperationStartTime) { + } else if yym14 { + z.EncBinaryMarshal(x.OperationStartTime) + } else if !yym14 && z.IsJSONHandle() { + z.EncJSONMarshal(x.OperationStartTime) + } else { + z.EncFallback(x.OperationStartTime) + } + } + } + } + if yyr2 || yy2arr2 { + z.EncSendContainerState(codecSelfer_containerArrayElem1234) + if yyq2[4] { + if x.InProgressProperties == nil { + r.EncodeNil() + } else { + x.InProgressProperties.CodecEncodeSelf(e) + } + } else { + r.EncodeNil() + } + } else { + if yyq2[4] { + z.EncSendContainerState(codecSelfer_containerMapKey1234) + r.EncodeString(codecSelferC_UTF81234, string("inProgressProperties")) + z.EncSendContainerState(codecSelfer_containerMapValue1234) + if x.InProgressProperties == nil { + r.EncodeNil() + } else { + x.InProgressProperties.CodecEncodeSelf(e) + } + } + } + if yyr2 || yy2arr2 { + z.EncSendContainerState(codecSelfer_containerArrayElem1234) + if yyq2[5] { + if x.ExternalProperties == nil { + r.EncodeNil() + } else { + x.ExternalProperties.CodecEncodeSelf(e) + } + } else { + r.EncodeNil() + } + } else { + if yyq2[5] { + z.EncSendContainerState(codecSelfer_containerMapKey1234) + r.EncodeString(codecSelferC_UTF81234, string("externalProperties")) + z.EncSendContainerState(codecSelfer_containerMapValue1234) + if x.ExternalProperties == nil { + r.EncodeNil() + } else { + x.ExternalProperties.CodecEncodeSelf(e) + } + } + } + if yyr2 || yy2arr2 { + z.EncSendContainerState(codecSelfer_containerArrayEnd1234) + } else { + z.EncSendContainerState(codecSelfer_containerMapEnd1234) + } + } + } +} + +func (x *ServiceInstanceCredentialStatus) CodecDecodeSelf(d *codec1978.Decoder) { + var h codecSelfer1234 + z, r := codec1978.GenHelperDecoder(d) + _, _, _ = h, z, r + yym1 := z.DecBinary() + _ = yym1 + if false { + } else if z.HasExtensions() && z.DecExt(x) { + } else { + yyct2 := r.ContainerType() + if yyct2 == codecSelferValueTypeMap1234 { + yyl2 := r.ReadMapStart() + if yyl2 == 0 { + z.DecSendContainerState(codecSelfer_containerMapEnd1234) + } else { + x.codecDecodeSelfFromMap(yyl2, d) + } + } else if yyct2 == codecSelferValueTypeArray1234 { + yyl2 := r.ReadArrayStart() + if yyl2 == 0 { + z.DecSendContainerState(codecSelfer_containerArrayEnd1234) + } else { + x.codecDecodeSelfFromArray(yyl2, d) + } + } else { + panic(codecSelferOnlyMapOrArrayEncodeToStructErr1234) + } + } +} + +func (x *ServiceInstanceCredentialStatus) codecDecodeSelfFromMap(l int, d *codec1978.Decoder) { + var h codecSelfer1234 + z, r := codec1978.GenHelperDecoder(d) + _, _, _ = h, z, r + var yys3Slc = z.DecScratchBuffer() // default slice to decode into + _ = yys3Slc + var yyhl3 bool = l >= 0 + for yyj3 := 0; ; yyj3++ { + if yyhl3 { + if yyj3 >= l { + break + } + } else { + if r.CheckBreak() { + break + } + } + z.DecSendContainerState(codecSelfer_containerMapKey1234) + yys3Slc = r.DecodeBytes(yys3Slc, true, true) + yys3 := string(yys3Slc) + z.DecSendContainerState(codecSelfer_containerMapValue1234) + switch yys3 { + case "conditions": + if r.TryDecodeAsNil() { + x.Conditions = nil + } else { + yyv4 := &x.Conditions + yym5 := z.DecBinary() + _ = yym5 + if false { + } else { + h.decSliceServiceInstanceCredentialCondition((*[]ServiceInstanceCredentialCondition)(yyv4), d) + } + } + case "currentOperation": + if r.TryDecodeAsNil() { + x.CurrentOperation = "" + } else { + yyv6 := &x.CurrentOperation + yyv6.CodecDecodeSelf(d) + } + case "reconciledGeneration": + if r.TryDecodeAsNil() { + x.ReconciledGeneration = 0 + } else { + yyv7 := &x.ReconciledGeneration + yym8 := z.DecBinary() + _ = yym8 + if false { + } else { + *((*int64)(yyv7)) = int64(r.DecodeInt(64)) + } + } + case "operationStartTime": + if r.TryDecodeAsNil() { + if x.OperationStartTime != nil { + x.OperationStartTime = nil + } + } else { + if x.OperationStartTime == nil { + x.OperationStartTime = new(pkg1_v1.Time) + } + yym10 := z.DecBinary() + _ = yym10 + if false { + } else if z.HasExtensions() && z.DecExt(x.OperationStartTime) { + } else if yym10 { + z.DecBinaryUnmarshal(x.OperationStartTime) + } else if !yym10 && z.IsJSONHandle() { + z.DecJSONUnmarshal(x.OperationStartTime) + } else { + z.DecFallback(x.OperationStartTime, false) + } + } + case "inProgressProperties": + if r.TryDecodeAsNil() { + if x.InProgressProperties != nil { + x.InProgressProperties = nil + } + } else { + if x.InProgressProperties == nil { + x.InProgressProperties = new(ServiceInstanceCredentialPropertiesState) + } + x.InProgressProperties.CodecDecodeSelf(d) + } + case "externalProperties": + if r.TryDecodeAsNil() { + if x.ExternalProperties != nil { + x.ExternalProperties = nil + } + } else { + if x.ExternalProperties == nil { + x.ExternalProperties = new(ServiceInstanceCredentialPropertiesState) + } + x.ExternalProperties.CodecDecodeSelf(d) + } + default: + z.DecStructFieldNotFound(-1, yys3) + } // end switch yys3 + } // end for yyj3 + z.DecSendContainerState(codecSelfer_containerMapEnd1234) +} + +func (x *ServiceInstanceCredentialStatus) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) { + var h codecSelfer1234 + z, r := codec1978.GenHelperDecoder(d) + _, _, _ = h, z, r + var yyj13 int + var yyb13 bool + var yyhl13 bool = l >= 0 + yyj13++ + if yyhl13 { + yyb13 = yyj13 > l + } else { + yyb13 = r.CheckBreak() + } + if yyb13 { + z.DecSendContainerState(codecSelfer_containerArrayEnd1234) + return + } + z.DecSendContainerState(codecSelfer_containerArrayElem1234) + if r.TryDecodeAsNil() { + x.Conditions = nil + } else { + yyv14 := &x.Conditions + yym15 := z.DecBinary() + _ = yym15 + if false { + } else { + h.decSliceServiceInstanceCredentialCondition((*[]ServiceInstanceCredentialCondition)(yyv14), d) + } + } + yyj13++ + if yyhl13 { + yyb13 = yyj13 > l + } else { + yyb13 = r.CheckBreak() + } + if yyb13 { + z.DecSendContainerState(codecSelfer_containerArrayEnd1234) + return + } + z.DecSendContainerState(codecSelfer_containerArrayElem1234) + if r.TryDecodeAsNil() { + x.CurrentOperation = "" + } else { + yyv16 := &x.CurrentOperation + yyv16.CodecDecodeSelf(d) + } + yyj13++ + if yyhl13 { + yyb13 = yyj13 > l + } else { + yyb13 = r.CheckBreak() + } + if yyb13 { + z.DecSendContainerState(codecSelfer_containerArrayEnd1234) + return + } + z.DecSendContainerState(codecSelfer_containerArrayElem1234) + if r.TryDecodeAsNil() { + x.ReconciledGeneration = 0 + } else { + yyv17 := &x.ReconciledGeneration + yym18 := z.DecBinary() + _ = yym18 + if false { + } else { + *((*int64)(yyv17)) = int64(r.DecodeInt(64)) + } + } + yyj13++ + if yyhl13 { + yyb13 = yyj13 > l } else { - yyb14 = r.CheckBreak() + yyb13 = r.CheckBreak() } - if yyb14 { + if yyb13 { z.DecSendContainerState(codecSelfer_containerArrayEnd1234) return } z.DecSendContainerState(codecSelfer_containerArrayElem1234) if r.TryDecodeAsNil() { - x.SecretName = "" + if x.OperationStartTime != nil { + x.OperationStartTime = nil + } } else { - yyv20 := &x.SecretName - yym21 := z.DecBinary() - _ = yym21 + if x.OperationStartTime == nil { + x.OperationStartTime = new(pkg1_v1.Time) + } + yym20 := z.DecBinary() + _ = yym20 if false { + } else if z.HasExtensions() && z.DecExt(x.OperationStartTime) { + } else if yym20 { + z.DecBinaryUnmarshal(x.OperationStartTime) + } else if !yym20 && z.IsJSONHandle() { + z.DecJSONUnmarshal(x.OperationStartTime) } else { - *((*string)(yyv20)) = r.DecodeString() + z.DecFallback(x.OperationStartTime, false) } } - yyj14++ - if yyhl14 { - yyb14 = yyj14 > l + yyj13++ + if yyhl13 { + yyb13 = yyj13 > l } else { - yyb14 = r.CheckBreak() + yyb13 = r.CheckBreak() } - if yyb14 { + if yyb13 { z.DecSendContainerState(codecSelfer_containerArrayEnd1234) return } z.DecSendContainerState(codecSelfer_containerArrayElem1234) if r.TryDecodeAsNil() { - x.ExternalID = "" + if x.InProgressProperties != nil { + x.InProgressProperties = nil + } } else { - yyv22 := &x.ExternalID - yym23 := z.DecBinary() - _ = yym23 - if false { - } else { - *((*string)(yyv22)) = r.DecodeString() + if x.InProgressProperties == nil { + x.InProgressProperties = new(ServiceInstanceCredentialPropertiesState) } + x.InProgressProperties.CodecDecodeSelf(d) } - yyj14++ - if yyhl14 { - yyb14 = yyj14 > l + yyj13++ + if yyhl13 { + yyb13 = yyj13 > l } else { - yyb14 = r.CheckBreak() + yyb13 = r.CheckBreak() } - if yyb14 { + if yyb13 { z.DecSendContainerState(codecSelfer_containerArrayEnd1234) return } z.DecSendContainerState(codecSelfer_containerArrayElem1234) if r.TryDecodeAsNil() { - if x.UserInfo != nil { - x.UserInfo = nil + if x.ExternalProperties != nil { + x.ExternalProperties = nil } } else { - if x.UserInfo == nil { - x.UserInfo = new(UserInfo) + if x.ExternalProperties == nil { + x.ExternalProperties = new(ServiceInstanceCredentialPropertiesState) } - x.UserInfo.CodecDecodeSelf(d) + x.ExternalProperties.CodecDecodeSelf(d) } for { - yyj14++ - if yyhl14 { - yyb14 = yyj14 > l + yyj13++ + if yyhl13 { + yyb13 = yyj13 > l } else { - yyb14 = r.CheckBreak() + yyb13 = r.CheckBreak() } - if yyb14 { + if yyb13 { break } z.DecSendContainerState(codecSelfer_containerArrayElem1234) - z.DecStructFieldNotFound(yyj14-1, "") + z.DecStructFieldNotFound(yyj13-1, "") } z.DecSendContainerState(codecSelfer_containerArrayEnd1234) } -func (x *ServiceInstanceCredentialStatus) CodecEncodeSelf(e *codec1978.Encoder) { +func (x *ServiceInstanceCredentialCondition) CodecEncodeSelf(e *codec1978.Encoder) { var h codecSelfer1234 z, r := codec1978.GenHelperEncoder(e) _, _, _ = h, z, r @@ -9493,16 +10466,14 @@ func (x *ServiceInstanceCredentialStatus) CodecEncodeSelf(e *codec1978.Encoder) } else { yysep2 := !z.EncBinary() yy2arr2 := z.EncBasicHandle().StructToArray - var yyq2 [4]bool + var yyq2 [5]bool _, _, _ = yysep2, yyq2, yy2arr2 const yyr2 bool = false - yyq2[1] = x.CurrentOperation != "" - yyq2[3] = x.OperationStartTime != nil var yynn2 int if yyr2 || yy2arr2 { - r.EncodeArrayStart(4) + r.EncodeArrayStart(5) } else { - yynn2 = 2 + yynn2 = 5 for _, b := range yyq2 { if b { yynn2++ @@ -9513,106 +10484,89 @@ func (x *ServiceInstanceCredentialStatus) CodecEncodeSelf(e *codec1978.Encoder) } if yyr2 || yy2arr2 { z.EncSendContainerState(codecSelfer_containerArrayElem1234) - if x.Conditions == nil { - r.EncodeNil() - } else { - yym4 := z.EncBinary() - _ = yym4 - if false { - } else { - h.encSliceServiceInstanceCredentialCondition(([]ServiceInstanceCredentialCondition)(x.Conditions), e) - } - } + x.Type.CodecEncodeSelf(e) } else { z.EncSendContainerState(codecSelfer_containerMapKey1234) - r.EncodeString(codecSelferC_UTF81234, string("conditions")) + r.EncodeString(codecSelferC_UTF81234, string("type")) z.EncSendContainerState(codecSelfer_containerMapValue1234) - if x.Conditions == nil { - r.EncodeNil() - } else { - yym5 := z.EncBinary() - _ = yym5 - if false { - } else { - h.encSliceServiceInstanceCredentialCondition(([]ServiceInstanceCredentialCondition)(x.Conditions), e) - } - } + x.Type.CodecEncodeSelf(e) } if yyr2 || yy2arr2 { z.EncSendContainerState(codecSelfer_containerArrayElem1234) - if yyq2[1] { - x.CurrentOperation.CodecEncodeSelf(e) + x.Status.CodecEncodeSelf(e) + } else { + z.EncSendContainerState(codecSelfer_containerMapKey1234) + r.EncodeString(codecSelferC_UTF81234, string("status")) + z.EncSendContainerState(codecSelfer_containerMapValue1234) + x.Status.CodecEncodeSelf(e) + } + if yyr2 || yy2arr2 { + z.EncSendContainerState(codecSelfer_containerArrayElem1234) + yy10 := &x.LastTransitionTime + yym11 := z.EncBinary() + _ = yym11 + if false { + } else if z.HasExtensions() && z.EncExt(yy10) { + } else if yym11 { + z.EncBinaryMarshal(yy10) + } else if !yym11 && z.IsJSONHandle() { + z.EncJSONMarshal(yy10) } else { - r.EncodeString(codecSelferC_UTF81234, "") + z.EncFallback(yy10) } } else { - if yyq2[1] { - z.EncSendContainerState(codecSelfer_containerMapKey1234) - r.EncodeString(codecSelferC_UTF81234, string("currentOperation")) - z.EncSendContainerState(codecSelfer_containerMapValue1234) - x.CurrentOperation.CodecEncodeSelf(e) + z.EncSendContainerState(codecSelfer_containerMapKey1234) + r.EncodeString(codecSelferC_UTF81234, string("lastTransitionTime")) + z.EncSendContainerState(codecSelfer_containerMapValue1234) + yy12 := &x.LastTransitionTime + yym13 := z.EncBinary() + _ = yym13 + if false { + } else if z.HasExtensions() && z.EncExt(yy12) { + } else if yym13 { + z.EncBinaryMarshal(yy12) + } else if !yym13 && z.IsJSONHandle() { + z.EncJSONMarshal(yy12) + } else { + z.EncFallback(yy12) } } if yyr2 || yy2arr2 { z.EncSendContainerState(codecSelfer_containerArrayElem1234) - yym10 := z.EncBinary() - _ = yym10 + yym15 := z.EncBinary() + _ = yym15 if false { } else { - r.EncodeInt(int64(x.ReconciledGeneration)) + r.EncodeString(codecSelferC_UTF81234, string(x.Reason)) } } else { z.EncSendContainerState(codecSelfer_containerMapKey1234) - r.EncodeString(codecSelferC_UTF81234, string("reconciledGeneration")) + r.EncodeString(codecSelferC_UTF81234, string("reason")) z.EncSendContainerState(codecSelfer_containerMapValue1234) - yym11 := z.EncBinary() - _ = yym11 + yym16 := z.EncBinary() + _ = yym16 if false { } else { - r.EncodeInt(int64(x.ReconciledGeneration)) + r.EncodeString(codecSelferC_UTF81234, string(x.Reason)) } } if yyr2 || yy2arr2 { z.EncSendContainerState(codecSelfer_containerArrayElem1234) - if yyq2[3] { - if x.OperationStartTime == nil { - r.EncodeNil() - } else { - yym13 := z.EncBinary() - _ = yym13 - if false { - } else if z.HasExtensions() && z.EncExt(x.OperationStartTime) { - } else if yym13 { - z.EncBinaryMarshal(x.OperationStartTime) - } else if !yym13 && z.IsJSONHandle() { - z.EncJSONMarshal(x.OperationStartTime) - } else { - z.EncFallback(x.OperationStartTime) - } - } + yym18 := z.EncBinary() + _ = yym18 + if false { } else { - r.EncodeNil() + r.EncodeString(codecSelferC_UTF81234, string(x.Message)) } } else { - if yyq2[3] { - z.EncSendContainerState(codecSelfer_containerMapKey1234) - r.EncodeString(codecSelferC_UTF81234, string("operationStartTime")) - z.EncSendContainerState(codecSelfer_containerMapValue1234) - if x.OperationStartTime == nil { - r.EncodeNil() - } else { - yym14 := z.EncBinary() - _ = yym14 - if false { - } else if z.HasExtensions() && z.EncExt(x.OperationStartTime) { - } else if yym14 { - z.EncBinaryMarshal(x.OperationStartTime) - } else if !yym14 && z.IsJSONHandle() { - z.EncJSONMarshal(x.OperationStartTime) - } else { - z.EncFallback(x.OperationStartTime) - } - } + z.EncSendContainerState(codecSelfer_containerMapKey1234) + r.EncodeString(codecSelferC_UTF81234, string("message")) + z.EncSendContainerState(codecSelfer_containerMapValue1234) + yym19 := z.EncBinary() + _ = yym19 + if false { + } else { + r.EncodeString(codecSelferC_UTF81234, string(x.Message)) } } if yyr2 || yy2arr2 { @@ -9624,7 +10578,7 @@ func (x *ServiceInstanceCredentialStatus) CodecEncodeSelf(e *codec1978.Encoder) } } -func (x *ServiceInstanceCredentialStatus) CodecDecodeSelf(d *codec1978.Decoder) { +func (x *ServiceInstanceCredentialCondition) CodecDecodeSelf(d *codec1978.Decoder) { var h codecSelfer1234 z, r := codec1978.GenHelperDecoder(d) _, _, _ = h, z, r @@ -9654,7 +10608,7 @@ func (x *ServiceInstanceCredentialStatus) CodecDecodeSelf(d *codec1978.Decoder) } } -func (x *ServiceInstanceCredentialStatus) codecDecodeSelfFromMap(l int, d *codec1978.Decoder) { +func (x *ServiceInstanceCredentialCondition) codecDecodeSelfFromMap(l int, d *codec1978.Decoder) { var h codecSelfer1234 z, r := codec1978.GenHelperDecoder(d) _, _, _ = h, z, r @@ -9676,56 +10630,59 @@ func (x *ServiceInstanceCredentialStatus) codecDecodeSelfFromMap(l int, d *codec yys3 := string(yys3Slc) z.DecSendContainerState(codecSelfer_containerMapValue1234) switch yys3 { - case "conditions": + case "type": if r.TryDecodeAsNil() { - x.Conditions = nil + x.Type = "" } else { - yyv4 := &x.Conditions - yym5 := z.DecBinary() - _ = yym5 - if false { - } else { - h.decSliceServiceInstanceCredentialCondition((*[]ServiceInstanceCredentialCondition)(yyv4), d) - } + yyv4 := &x.Type + yyv4.CodecDecodeSelf(d) } - case "currentOperation": + case "status": if r.TryDecodeAsNil() { - x.CurrentOperation = "" + x.Status = "" } else { - yyv6 := &x.CurrentOperation - yyv6.CodecDecodeSelf(d) + yyv5 := &x.Status + yyv5.CodecDecodeSelf(d) } - case "reconciledGeneration": + case "lastTransitionTime": if r.TryDecodeAsNil() { - x.ReconciledGeneration = 0 + x.LastTransitionTime = pkg1_v1.Time{} } else { - yyv7 := &x.ReconciledGeneration - yym8 := z.DecBinary() - _ = yym8 + yyv6 := &x.LastTransitionTime + yym7 := z.DecBinary() + _ = yym7 if false { + } else if z.HasExtensions() && z.DecExt(yyv6) { + } else if yym7 { + z.DecBinaryUnmarshal(yyv6) + } else if !yym7 && z.IsJSONHandle() { + z.DecJSONUnmarshal(yyv6) } else { - *((*int64)(yyv7)) = int64(r.DecodeInt(64)) + z.DecFallback(yyv6, false) } } - case "operationStartTime": + case "reason": if r.TryDecodeAsNil() { - if x.OperationStartTime != nil { - x.OperationStartTime = nil - } + x.Reason = "" } else { - if x.OperationStartTime == nil { - x.OperationStartTime = new(pkg1_v1.Time) - } - yym10 := z.DecBinary() - _ = yym10 + yyv8 := &x.Reason + yym9 := z.DecBinary() + _ = yym9 + if false { + } else { + *((*string)(yyv8)) = r.DecodeString() + } + } + case "message": + if r.TryDecodeAsNil() { + x.Message = "" + } else { + yyv10 := &x.Message + yym11 := z.DecBinary() + _ = yym11 if false { - } else if z.HasExtensions() && z.DecExt(x.OperationStartTime) { - } else if yym10 { - z.DecBinaryUnmarshal(x.OperationStartTime) - } else if !yym10 && z.IsJSONHandle() { - z.DecJSONUnmarshal(x.OperationStartTime) } else { - z.DecFallback(x.OperationStartTime, false) + *((*string)(yyv10)) = r.DecodeString() } } default: @@ -9735,122 +10692,187 @@ func (x *ServiceInstanceCredentialStatus) codecDecodeSelfFromMap(l int, d *codec z.DecSendContainerState(codecSelfer_containerMapEnd1234) } -func (x *ServiceInstanceCredentialStatus) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) { +func (x *ServiceInstanceCredentialCondition) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) { var h codecSelfer1234 z, r := codec1978.GenHelperDecoder(d) _, _, _ = h, z, r - var yyj11 int - var yyb11 bool - var yyhl11 bool = l >= 0 - yyj11++ - if yyhl11 { - yyb11 = yyj11 > l + var yyj12 int + var yyb12 bool + var yyhl12 bool = l >= 0 + yyj12++ + if yyhl12 { + yyb12 = yyj12 > l } else { - yyb11 = r.CheckBreak() + yyb12 = r.CheckBreak() } - if yyb11 { + if yyb12 { z.DecSendContainerState(codecSelfer_containerArrayEnd1234) return } z.DecSendContainerState(codecSelfer_containerArrayElem1234) if r.TryDecodeAsNil() { - x.Conditions = nil + x.Type = "" } else { - yyv12 := &x.Conditions - yym13 := z.DecBinary() - _ = yym13 - if false { - } else { - h.decSliceServiceInstanceCredentialCondition((*[]ServiceInstanceCredentialCondition)(yyv12), d) - } + yyv13 := &x.Type + yyv13.CodecDecodeSelf(d) } - yyj11++ - if yyhl11 { - yyb11 = yyj11 > l + yyj12++ + if yyhl12 { + yyb12 = yyj12 > l } else { - yyb11 = r.CheckBreak() + yyb12 = r.CheckBreak() } - if yyb11 { + if yyb12 { z.DecSendContainerState(codecSelfer_containerArrayEnd1234) return } z.DecSendContainerState(codecSelfer_containerArrayElem1234) if r.TryDecodeAsNil() { - x.CurrentOperation = "" + x.Status = "" } else { - yyv14 := &x.CurrentOperation + yyv14 := &x.Status yyv14.CodecDecodeSelf(d) } - yyj11++ - if yyhl11 { - yyb11 = yyj11 > l + yyj12++ + if yyhl12 { + yyb12 = yyj12 > l } else { - yyb11 = r.CheckBreak() + yyb12 = r.CheckBreak() } - if yyb11 { + if yyb12 { z.DecSendContainerState(codecSelfer_containerArrayEnd1234) return } z.DecSendContainerState(codecSelfer_containerArrayElem1234) if r.TryDecodeAsNil() { - x.ReconciledGeneration = 0 + x.LastTransitionTime = pkg1_v1.Time{} } else { - yyv15 := &x.ReconciledGeneration + yyv15 := &x.LastTransitionTime yym16 := z.DecBinary() _ = yym16 if false { + } else if z.HasExtensions() && z.DecExt(yyv15) { + } else if yym16 { + z.DecBinaryUnmarshal(yyv15) + } else if !yym16 && z.IsJSONHandle() { + z.DecJSONUnmarshal(yyv15) } else { - *((*int64)(yyv15)) = int64(r.DecodeInt(64)) + z.DecFallback(yyv15, false) } } - yyj11++ - if yyhl11 { - yyb11 = yyj11 > l + yyj12++ + if yyhl12 { + yyb12 = yyj12 > l } else { - yyb11 = r.CheckBreak() + yyb12 = r.CheckBreak() } - if yyb11 { + if yyb12 { z.DecSendContainerState(codecSelfer_containerArrayEnd1234) return } z.DecSendContainerState(codecSelfer_containerArrayElem1234) if r.TryDecodeAsNil() { - if x.OperationStartTime != nil { - x.OperationStartTime = nil - } + x.Reason = "" } else { - if x.OperationStartTime == nil { - x.OperationStartTime = new(pkg1_v1.Time) - } + yyv17 := &x.Reason yym18 := z.DecBinary() _ = yym18 if false { - } else if z.HasExtensions() && z.DecExt(x.OperationStartTime) { - } else if yym18 { - z.DecBinaryUnmarshal(x.OperationStartTime) - } else if !yym18 && z.IsJSONHandle() { - z.DecJSONUnmarshal(x.OperationStartTime) } else { - z.DecFallback(x.OperationStartTime, false) + *((*string)(yyv17)) = r.DecodeString() + } + } + yyj12++ + if yyhl12 { + yyb12 = yyj12 > l + } else { + yyb12 = r.CheckBreak() + } + if yyb12 { + z.DecSendContainerState(codecSelfer_containerArrayEnd1234) + return + } + z.DecSendContainerState(codecSelfer_containerArrayElem1234) + if r.TryDecodeAsNil() { + x.Message = "" + } else { + yyv19 := &x.Message + yym20 := z.DecBinary() + _ = yym20 + if false { + } else { + *((*string)(yyv19)) = r.DecodeString() } } for { - yyj11++ - if yyhl11 { - yyb11 = yyj11 > l + yyj12++ + if yyhl12 { + yyb12 = yyj12 > l } else { - yyb11 = r.CheckBreak() + yyb12 = r.CheckBreak() } - if yyb11 { + if yyb12 { break } z.DecSendContainerState(codecSelfer_containerArrayElem1234) - z.DecStructFieldNotFound(yyj11-1, "") + z.DecStructFieldNotFound(yyj12-1, "") } z.DecSendContainerState(codecSelfer_containerArrayEnd1234) } -func (x *ServiceInstanceCredentialCondition) CodecEncodeSelf(e *codec1978.Encoder) { +func (x ServiceInstanceCredentialConditionType) CodecEncodeSelf(e *codec1978.Encoder) { + var h codecSelfer1234 + z, r := codec1978.GenHelperEncoder(e) + _, _, _ = h, z, r + yym1 := z.EncBinary() + _ = yym1 + if false { + } else if z.HasExtensions() && z.EncExt(x) { + } else { + r.EncodeString(codecSelferC_UTF81234, string(x)) + } +} + +func (x *ServiceInstanceCredentialConditionType) CodecDecodeSelf(d *codec1978.Decoder) { + var h codecSelfer1234 + z, r := codec1978.GenHelperDecoder(d) + _, _, _ = h, z, r + yym1 := z.DecBinary() + _ = yym1 + if false { + } else if z.HasExtensions() && z.DecExt(x) { + } else { + *((*string)(x)) = r.DecodeString() + } +} + +func (x ServiceInstanceCredentialOperation) CodecEncodeSelf(e *codec1978.Encoder) { + var h codecSelfer1234 + z, r := codec1978.GenHelperEncoder(e) + _, _, _ = h, z, r + yym1 := z.EncBinary() + _ = yym1 + if false { + } else if z.HasExtensions() && z.EncExt(x) { + } else { + r.EncodeString(codecSelferC_UTF81234, string(x)) + } +} + +func (x *ServiceInstanceCredentialOperation) CodecDecodeSelf(d *codec1978.Decoder) { + var h codecSelfer1234 + z, r := codec1978.GenHelperDecoder(d) + _, _, _ = h, z, r + yym1 := z.DecBinary() + _ = yym1 + if false { + } else if z.HasExtensions() && z.DecExt(x) { + } else { + *((*string)(x)) = r.DecodeString() + } +} + +func (x *ServiceInstanceCredentialPropertiesState) CodecEncodeSelf(e *codec1978.Encoder) { var h codecSelfer1234 z, r := codec1978.GenHelperEncoder(e) _, _, _ = h, z, r @@ -9864,14 +10886,17 @@ func (x *ServiceInstanceCredentialCondition) CodecEncodeSelf(e *codec1978.Encode } else { yysep2 := !z.EncBinary() yy2arr2 := z.EncBasicHandle().StructToArray - var yyq2 [5]bool + var yyq2 [3]bool _, _, _ = yysep2, yyq2, yy2arr2 const yyr2 bool = false + yyq2[0] = x.Parameters != nil + yyq2[1] = x.ParametersChecksum != "" + yyq2[2] = x.UserInfo != nil var yynn2 int if yyr2 || yy2arr2 { - r.EncodeArrayStart(5) + r.EncodeArrayStart(3) } else { - yynn2 = 5 + yynn2 = 0 for _, b := range yyq2 { if b { yynn2++ @@ -9882,89 +10907,89 @@ func (x *ServiceInstanceCredentialCondition) CodecEncodeSelf(e *codec1978.Encode } if yyr2 || yy2arr2 { z.EncSendContainerState(codecSelfer_containerArrayElem1234) - x.Type.CodecEncodeSelf(e) - } else { - z.EncSendContainerState(codecSelfer_containerMapKey1234) - r.EncodeString(codecSelferC_UTF81234, string("type")) - z.EncSendContainerState(codecSelfer_containerMapValue1234) - x.Type.CodecEncodeSelf(e) - } - if yyr2 || yy2arr2 { - z.EncSendContainerState(codecSelfer_containerArrayElem1234) - x.Status.CodecEncodeSelf(e) - } else { - z.EncSendContainerState(codecSelfer_containerMapKey1234) - r.EncodeString(codecSelferC_UTF81234, string("status")) - z.EncSendContainerState(codecSelfer_containerMapValue1234) - x.Status.CodecEncodeSelf(e) - } - if yyr2 || yy2arr2 { - z.EncSendContainerState(codecSelfer_containerArrayElem1234) - yy10 := &x.LastTransitionTime - yym11 := z.EncBinary() - _ = yym11 - if false { - } else if z.HasExtensions() && z.EncExt(yy10) { - } else if yym11 { - z.EncBinaryMarshal(yy10) - } else if !yym11 && z.IsJSONHandle() { - z.EncJSONMarshal(yy10) + if yyq2[0] { + if x.Parameters == nil { + r.EncodeNil() + } else { + yym4 := z.EncBinary() + _ = yym4 + if false { + } else if z.HasExtensions() && z.EncExt(x.Parameters) { + } else if !yym4 && z.IsJSONHandle() { + z.EncJSONMarshal(x.Parameters) + } else { + z.EncFallback(x.Parameters) + } + } } else { - z.EncFallback(yy10) + r.EncodeNil() } } else { - z.EncSendContainerState(codecSelfer_containerMapKey1234) - r.EncodeString(codecSelferC_UTF81234, string("lastTransitionTime")) - z.EncSendContainerState(codecSelfer_containerMapValue1234) - yy12 := &x.LastTransitionTime - yym13 := z.EncBinary() - _ = yym13 - if false { - } else if z.HasExtensions() && z.EncExt(yy12) { - } else if yym13 { - z.EncBinaryMarshal(yy12) - } else if !yym13 && z.IsJSONHandle() { - z.EncJSONMarshal(yy12) - } else { - z.EncFallback(yy12) + if yyq2[0] { + z.EncSendContainerState(codecSelfer_containerMapKey1234) + r.EncodeString(codecSelferC_UTF81234, string("parameters")) + z.EncSendContainerState(codecSelfer_containerMapValue1234) + if x.Parameters == nil { + r.EncodeNil() + } else { + yym5 := z.EncBinary() + _ = yym5 + if false { + } else if z.HasExtensions() && z.EncExt(x.Parameters) { + } else if !yym5 && z.IsJSONHandle() { + z.EncJSONMarshal(x.Parameters) + } else { + z.EncFallback(x.Parameters) + } + } } } if yyr2 || yy2arr2 { z.EncSendContainerState(codecSelfer_containerArrayElem1234) - yym15 := z.EncBinary() - _ = yym15 - if false { + if yyq2[1] { + yym7 := z.EncBinary() + _ = yym7 + if false { + } else { + r.EncodeString(codecSelferC_UTF81234, string(x.ParametersChecksum)) + } } else { - r.EncodeString(codecSelferC_UTF81234, string(x.Reason)) + r.EncodeString(codecSelferC_UTF81234, "") } } else { - z.EncSendContainerState(codecSelfer_containerMapKey1234) - r.EncodeString(codecSelferC_UTF81234, string("reason")) - z.EncSendContainerState(codecSelfer_containerMapValue1234) - yym16 := z.EncBinary() - _ = yym16 - if false { - } else { - r.EncodeString(codecSelferC_UTF81234, string(x.Reason)) + if yyq2[1] { + z.EncSendContainerState(codecSelfer_containerMapKey1234) + r.EncodeString(codecSelferC_UTF81234, string("parameterChecksum")) + z.EncSendContainerState(codecSelfer_containerMapValue1234) + yym8 := z.EncBinary() + _ = yym8 + if false { + } else { + r.EncodeString(codecSelferC_UTF81234, string(x.ParametersChecksum)) + } } } if yyr2 || yy2arr2 { z.EncSendContainerState(codecSelfer_containerArrayElem1234) - yym18 := z.EncBinary() - _ = yym18 - if false { + if yyq2[2] { + if x.UserInfo == nil { + r.EncodeNil() + } else { + x.UserInfo.CodecEncodeSelf(e) + } } else { - r.EncodeString(codecSelferC_UTF81234, string(x.Message)) + r.EncodeNil() } } else { - z.EncSendContainerState(codecSelfer_containerMapKey1234) - r.EncodeString(codecSelferC_UTF81234, string("message")) - z.EncSendContainerState(codecSelfer_containerMapValue1234) - yym19 := z.EncBinary() - _ = yym19 - if false { - } else { - r.EncodeString(codecSelferC_UTF81234, string(x.Message)) + if yyq2[2] { + z.EncSendContainerState(codecSelfer_containerMapKey1234) + r.EncodeString(codecSelferC_UTF81234, string("userInfo")) + z.EncSendContainerState(codecSelfer_containerMapValue1234) + if x.UserInfo == nil { + r.EncodeNil() + } else { + x.UserInfo.CodecEncodeSelf(e) + } } } if yyr2 || yy2arr2 { @@ -9976,7 +11001,7 @@ func (x *ServiceInstanceCredentialCondition) CodecEncodeSelf(e *codec1978.Encode } } -func (x *ServiceInstanceCredentialCondition) CodecDecodeSelf(d *codec1978.Decoder) { +func (x *ServiceInstanceCredentialPropertiesState) CodecDecodeSelf(d *codec1978.Decoder) { var h codecSelfer1234 z, r := codec1978.GenHelperDecoder(d) _, _, _ = h, z, r @@ -10006,7 +11031,7 @@ func (x *ServiceInstanceCredentialCondition) CodecDecodeSelf(d *codec1978.Decode } } -func (x *ServiceInstanceCredentialCondition) codecDecodeSelfFromMap(l int, d *codec1978.Decoder) { +func (x *ServiceInstanceCredentialPropertiesState) codecDecodeSelfFromMap(l int, d *codec1978.Decoder) { var h codecSelfer1234 z, r := codec1978.GenHelperDecoder(d) _, _, _ = h, z, r @@ -10028,60 +11053,47 @@ func (x *ServiceInstanceCredentialCondition) codecDecodeSelfFromMap(l int, d *co yys3 := string(yys3Slc) z.DecSendContainerState(codecSelfer_containerMapValue1234) switch yys3 { - case "type": - if r.TryDecodeAsNil() { - x.Type = "" - } else { - yyv4 := &x.Type - yyv4.CodecDecodeSelf(d) - } - case "status": - if r.TryDecodeAsNil() { - x.Status = "" - } else { - yyv5 := &x.Status - yyv5.CodecDecodeSelf(d) - } - case "lastTransitionTime": + case "parameters": if r.TryDecodeAsNil() { - x.LastTransitionTime = pkg1_v1.Time{} + if x.Parameters != nil { + x.Parameters = nil + } } else { - yyv6 := &x.LastTransitionTime - yym7 := z.DecBinary() - _ = yym7 + if x.Parameters == nil { + x.Parameters = new(pkg4_runtime.RawExtension) + } + yym5 := z.DecBinary() + _ = yym5 if false { - } else if z.HasExtensions() && z.DecExt(yyv6) { - } else if yym7 { - z.DecBinaryUnmarshal(yyv6) - } else if !yym7 && z.IsJSONHandle() { - z.DecJSONUnmarshal(yyv6) + } else if z.HasExtensions() && z.DecExt(x.Parameters) { + } else if !yym5 && z.IsJSONHandle() { + z.DecJSONUnmarshal(x.Parameters) } else { - z.DecFallback(yyv6, false) + z.DecFallback(x.Parameters, false) } } - case "reason": + case "parameterChecksum": if r.TryDecodeAsNil() { - x.Reason = "" + x.ParametersChecksum = "" } else { - yyv8 := &x.Reason - yym9 := z.DecBinary() - _ = yym9 + yyv6 := &x.ParametersChecksum + yym7 := z.DecBinary() + _ = yym7 if false { } else { - *((*string)(yyv8)) = r.DecodeString() + *((*string)(yyv6)) = r.DecodeString() } } - case "message": + case "userInfo": if r.TryDecodeAsNil() { - x.Message = "" + if x.UserInfo != nil { + x.UserInfo = nil + } } else { - yyv10 := &x.Message - yym11 := z.DecBinary() - _ = yym11 - if false { - } else { - *((*string)(yyv10)) = r.DecodeString() + if x.UserInfo == nil { + x.UserInfo = new(UserInfo) } + x.UserInfo.CodecDecodeSelf(d) } default: z.DecStructFieldNotFound(-1, yys3) @@ -10090,186 +11102,101 @@ func (x *ServiceInstanceCredentialCondition) codecDecodeSelfFromMap(l int, d *co z.DecSendContainerState(codecSelfer_containerMapEnd1234) } -func (x *ServiceInstanceCredentialCondition) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) { +func (x *ServiceInstanceCredentialPropertiesState) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) { var h codecSelfer1234 z, r := codec1978.GenHelperDecoder(d) _, _, _ = h, z, r - var yyj12 int - var yyb12 bool - var yyhl12 bool = l >= 0 - yyj12++ - if yyhl12 { - yyb12 = yyj12 > l - } else { - yyb12 = r.CheckBreak() - } - if yyb12 { - z.DecSendContainerState(codecSelfer_containerArrayEnd1234) - return - } - z.DecSendContainerState(codecSelfer_containerArrayElem1234) - if r.TryDecodeAsNil() { - x.Type = "" - } else { - yyv13 := &x.Type - yyv13.CodecDecodeSelf(d) - } - yyj12++ - if yyhl12 { - yyb12 = yyj12 > l - } else { - yyb12 = r.CheckBreak() - } - if yyb12 { - z.DecSendContainerState(codecSelfer_containerArrayEnd1234) - return - } - z.DecSendContainerState(codecSelfer_containerArrayElem1234) - if r.TryDecodeAsNil() { - x.Status = "" - } else { - yyv14 := &x.Status - yyv14.CodecDecodeSelf(d) - } - yyj12++ - if yyhl12 { - yyb12 = yyj12 > l + var yyj9 int + var yyb9 bool + var yyhl9 bool = l >= 0 + yyj9++ + if yyhl9 { + yyb9 = yyj9 > l } else { - yyb12 = r.CheckBreak() + yyb9 = r.CheckBreak() } - if yyb12 { + if yyb9 { z.DecSendContainerState(codecSelfer_containerArrayEnd1234) return } z.DecSendContainerState(codecSelfer_containerArrayElem1234) if r.TryDecodeAsNil() { - x.LastTransitionTime = pkg1_v1.Time{} + if x.Parameters != nil { + x.Parameters = nil + } } else { - yyv15 := &x.LastTransitionTime - yym16 := z.DecBinary() - _ = yym16 + if x.Parameters == nil { + x.Parameters = new(pkg4_runtime.RawExtension) + } + yym11 := z.DecBinary() + _ = yym11 if false { - } else if z.HasExtensions() && z.DecExt(yyv15) { - } else if yym16 { - z.DecBinaryUnmarshal(yyv15) - } else if !yym16 && z.IsJSONHandle() { - z.DecJSONUnmarshal(yyv15) + } else if z.HasExtensions() && z.DecExt(x.Parameters) { + } else if !yym11 && z.IsJSONHandle() { + z.DecJSONUnmarshal(x.Parameters) } else { - z.DecFallback(yyv15, false) + z.DecFallback(x.Parameters, false) } } - yyj12++ - if yyhl12 { - yyb12 = yyj12 > l + yyj9++ + if yyhl9 { + yyb9 = yyj9 > l } else { - yyb12 = r.CheckBreak() + yyb9 = r.CheckBreak() } - if yyb12 { + if yyb9 { z.DecSendContainerState(codecSelfer_containerArrayEnd1234) return } z.DecSendContainerState(codecSelfer_containerArrayElem1234) if r.TryDecodeAsNil() { - x.Reason = "" + x.ParametersChecksum = "" } else { - yyv17 := &x.Reason - yym18 := z.DecBinary() - _ = yym18 + yyv12 := &x.ParametersChecksum + yym13 := z.DecBinary() + _ = yym13 if false { } else { - *((*string)(yyv17)) = r.DecodeString() + *((*string)(yyv12)) = r.DecodeString() } } - yyj12++ - if yyhl12 { - yyb12 = yyj12 > l + yyj9++ + if yyhl9 { + yyb9 = yyj9 > l } else { - yyb12 = r.CheckBreak() + yyb9 = r.CheckBreak() } - if yyb12 { + if yyb9 { z.DecSendContainerState(codecSelfer_containerArrayEnd1234) return } z.DecSendContainerState(codecSelfer_containerArrayElem1234) if r.TryDecodeAsNil() { - x.Message = "" + if x.UserInfo != nil { + x.UserInfo = nil + } } else { - yyv19 := &x.Message - yym20 := z.DecBinary() - _ = yym20 - if false { - } else { - *((*string)(yyv19)) = r.DecodeString() + if x.UserInfo == nil { + x.UserInfo = new(UserInfo) } + x.UserInfo.CodecDecodeSelf(d) } for { - yyj12++ - if yyhl12 { - yyb12 = yyj12 > l + yyj9++ + if yyhl9 { + yyb9 = yyj9 > l } else { - yyb12 = r.CheckBreak() + yyb9 = r.CheckBreak() } - if yyb12 { + if yyb9 { break } z.DecSendContainerState(codecSelfer_containerArrayElem1234) - z.DecStructFieldNotFound(yyj12-1, "") + z.DecStructFieldNotFound(yyj9-1, "") } z.DecSendContainerState(codecSelfer_containerArrayEnd1234) } -func (x ServiceInstanceCredentialConditionType) CodecEncodeSelf(e *codec1978.Encoder) { - var h codecSelfer1234 - z, r := codec1978.GenHelperEncoder(e) - _, _, _ = h, z, r - yym1 := z.EncBinary() - _ = yym1 - if false { - } else if z.HasExtensions() && z.EncExt(x) { - } else { - r.EncodeString(codecSelferC_UTF81234, string(x)) - } -} - -func (x *ServiceInstanceCredentialConditionType) CodecDecodeSelf(d *codec1978.Decoder) { - var h codecSelfer1234 - z, r := codec1978.GenHelperDecoder(d) - _, _, _ = h, z, r - yym1 := z.DecBinary() - _ = yym1 - if false { - } else if z.HasExtensions() && z.DecExt(x) { - } else { - *((*string)(x)) = r.DecodeString() - } -} - -func (x ServiceInstanceCredentialOperation) CodecEncodeSelf(e *codec1978.Encoder) { - var h codecSelfer1234 - z, r := codec1978.GenHelperEncoder(e) - _, _, _ = h, z, r - yym1 := z.EncBinary() - _ = yym1 - if false { - } else if z.HasExtensions() && z.EncExt(x) { - } else { - r.EncodeString(codecSelferC_UTF81234, string(x)) - } -} - -func (x *ServiceInstanceCredentialOperation) CodecDecodeSelf(d *codec1978.Decoder) { - var h codecSelfer1234 - z, r := codec1978.GenHelperDecoder(d) - _, _, _ = h, z, r - yym1 := z.DecBinary() - _ = yym1 - if false { - } else if z.HasExtensions() && z.DecExt(x) { - } else { - *((*string)(x)) = r.DecodeString() - } -} - func (x *ParametersFromSource) CodecEncodeSelf(e *codec1978.Encoder) { var h codecSelfer1234 z, r := codec1978.GenHelperEncoder(e) @@ -11189,7 +12116,7 @@ func (x codecSelfer1234) decSliceServiceInstance(v *[]ServiceInstance, d *codec1 yyrg1 := len(yyv1) > 0 yyv21 := yyv1 - yyrl1, yyrt1 = z.DecInferLen(yyl1, z.DecBasicHandle().MaxInitLen, 432) + yyrl1, yyrt1 = z.DecInferLen(yyl1, z.DecBasicHandle().MaxInitLen, 448) if yyrt1 { if yyrl1 <= cap(yyv1) { yyv1 = yyv1[:yyrl1] @@ -11789,7 +12716,7 @@ func (x codecSelfer1234) decSliceServiceInstanceCredential(v *[]ServiceInstanceC yyrg1 := len(yyv1) > 0 yyv21 := yyv1 - yyrl1, yyrt1 = z.DecInferLen(yyl1, z.DecBasicHandle().MaxInitLen, 408) + yyrl1, yyrt1 = z.DecInferLen(yyl1, z.DecBasicHandle().MaxInitLen, 424) if yyrt1 { if yyrl1 <= cap(yyv1) { yyv1 = yyv1[:yyrl1] diff --git a/pkg/apis/servicecatalog/v1alpha1/types.go b/pkg/apis/servicecatalog/v1alpha1/types.go index dbf39b37c17..dc790fb5157 100644 --- a/pkg/apis/servicecatalog/v1alpha1/types.go +++ b/pkg/apis/servicecatalog/v1alpha1/types.go @@ -462,6 +462,14 @@ type ServiceInstanceStatus struct { // OperationStartTime is the time at which the current operation began. OperationStartTime *metav1.Time `json:"operationStartTime,omitempty"` + + // InProgressProperties is the properties state for which there is a + // provision or update action in progress. + InProgressProperties *ServiceInstancePropertiesState `json:"inProgressProperties,omitempty"` + + // ExternalProperties is the properites state which the broker knows + // about. + ExternalProperties *ServiceInstancePropertiesState `json:"externalProperties,omitempty"` } // ServiceInstanceCondition contains condition information about an Instance. @@ -514,6 +522,25 @@ const ( ServiceInstanceOperationDeprovision ServiceInstanceOperation = "Deprovision" ) +// ServiceInstancePropertiesState is the state of a ServiceInstance that +// the ServiceBroker knows about. +type ServiceInstancePropertiesState struct { + // PlanName is the name of the plan that the broker knows this + // ServiceInstance to be on. + PlanName string `json:"planName"` + + // Parameters is a blob of the parameters and their values that the broker + // knows about for this ServiceInstance. If a parameter was sourced from + // a secret, its value will be "" in this blob. + Parameters *runtime.RawExtension `json:"parameters,omitempty"` + + // ParametersChecksum is the checksum of the parameters that were sent. + ParametersChecksum string `json:"parameterChecksum,omitempty"` + + // UserInfo is information about the user that made the request. + UserInfo *UserInfo `json:"userInfo,omitempty"` +} + // ServiceInstanceCredentialList is a list of ServiceInstanceCredentials. type ServiceInstanceCredentialList struct { metav1.TypeMeta `json:",inline"` @@ -597,6 +624,14 @@ type ServiceInstanceCredentialStatus struct { // OperationStartTime is the time at which the current operation began. OperationStartTime *metav1.Time `json:"operationStartTime,omitempty"` + + // InProgressProperties is the properties state for which there is a bind + // operation in progress. + InProgressProperties *ServiceInstanceCredentialPropertiesState `json:"inProgressProperties,omitempty"` + + // ExternalProperties is the properties state that the broker knows + // about for this ServiceInstanceCredential. + ExternalProperties *ServiceInstanceCredentialPropertiesState `json:"externalProperties,omitempty"` } // ServiceInstanceCredentialCondition condition information for a ServiceInstanceCredential. @@ -650,6 +685,21 @@ const ( FinalizerServiceCatalog string = "kubernetes-incubator/service-catalog" ) +// ServiceInstanceCredentialPropertiesState is the state of a +// ServiceInstanceCredential that the ServiceBroker knows about. +type ServiceInstanceCredentialPropertiesState struct { + // Parameters is a blob of the parameters and their values that the broker + // knows about for this ServiceInstanceCredential. If a parameter was + // sourced from a secret, its value will be "" in this blob. + Parameters *runtime.RawExtension `json:"parameters,omitempty"` + + // ParametersChecksum is the checksum of the parameters that were sent. + ParametersChecksum string `json:"parameterChecksum,omitempty"` + + // UserInfo is information about the user that made the request. + UserInfo *UserInfo `json:"userInfo,omitempty"` +} + // ParametersFromSource represents the source of a set of Parameters type ParametersFromSource struct { // The Secret key to select from. diff --git a/pkg/apis/servicecatalog/v1alpha1/zz_generated.conversion.go b/pkg/apis/servicecatalog/v1alpha1/zz_generated.conversion.go index b913fe31ab4..28b1c2b9810 100644 --- a/pkg/apis/servicecatalog/v1alpha1/zz_generated.conversion.go +++ b/pkg/apis/servicecatalog/v1alpha1/zz_generated.conversion.go @@ -73,12 +73,16 @@ func RegisterConversions(scheme *runtime.Scheme) error { Convert_servicecatalog_ServiceInstanceCredentialCondition_To_v1alpha1_ServiceInstanceCredentialCondition, Convert_v1alpha1_ServiceInstanceCredentialList_To_servicecatalog_ServiceInstanceCredentialList, Convert_servicecatalog_ServiceInstanceCredentialList_To_v1alpha1_ServiceInstanceCredentialList, + Convert_v1alpha1_ServiceInstanceCredentialPropertiesState_To_servicecatalog_ServiceInstanceCredentialPropertiesState, + Convert_servicecatalog_ServiceInstanceCredentialPropertiesState_To_v1alpha1_ServiceInstanceCredentialPropertiesState, Convert_v1alpha1_ServiceInstanceCredentialSpec_To_servicecatalog_ServiceInstanceCredentialSpec, Convert_servicecatalog_ServiceInstanceCredentialSpec_To_v1alpha1_ServiceInstanceCredentialSpec, Convert_v1alpha1_ServiceInstanceCredentialStatus_To_servicecatalog_ServiceInstanceCredentialStatus, Convert_servicecatalog_ServiceInstanceCredentialStatus_To_v1alpha1_ServiceInstanceCredentialStatus, Convert_v1alpha1_ServiceInstanceList_To_servicecatalog_ServiceInstanceList, Convert_servicecatalog_ServiceInstanceList_To_v1alpha1_ServiceInstanceList, + Convert_v1alpha1_ServiceInstancePropertiesState_To_servicecatalog_ServiceInstancePropertiesState, + Convert_servicecatalog_ServiceInstancePropertiesState_To_v1alpha1_ServiceInstancePropertiesState, Convert_v1alpha1_ServiceInstanceSpec_To_servicecatalog_ServiceInstanceSpec, Convert_servicecatalog_ServiceInstanceSpec_To_v1alpha1_ServiceInstanceSpec, Convert_v1alpha1_ServiceInstanceStatus_To_servicecatalog_ServiceInstanceStatus, @@ -580,6 +584,30 @@ func Convert_servicecatalog_ServiceInstanceCredentialList_To_v1alpha1_ServiceIns return autoConvert_servicecatalog_ServiceInstanceCredentialList_To_v1alpha1_ServiceInstanceCredentialList(in, out, s) } +func autoConvert_v1alpha1_ServiceInstanceCredentialPropertiesState_To_servicecatalog_ServiceInstanceCredentialPropertiesState(in *ServiceInstanceCredentialPropertiesState, out *servicecatalog.ServiceInstanceCredentialPropertiesState, s conversion.Scope) error { + out.Parameters = (*runtime.RawExtension)(unsafe.Pointer(in.Parameters)) + out.ParametersChecksum = in.ParametersChecksum + out.UserInfo = (*servicecatalog.UserInfo)(unsafe.Pointer(in.UserInfo)) + return nil +} + +// Convert_v1alpha1_ServiceInstanceCredentialPropertiesState_To_servicecatalog_ServiceInstanceCredentialPropertiesState is an autogenerated conversion function. +func Convert_v1alpha1_ServiceInstanceCredentialPropertiesState_To_servicecatalog_ServiceInstanceCredentialPropertiesState(in *ServiceInstanceCredentialPropertiesState, out *servicecatalog.ServiceInstanceCredentialPropertiesState, s conversion.Scope) error { + return autoConvert_v1alpha1_ServiceInstanceCredentialPropertiesState_To_servicecatalog_ServiceInstanceCredentialPropertiesState(in, out, s) +} + +func autoConvert_servicecatalog_ServiceInstanceCredentialPropertiesState_To_v1alpha1_ServiceInstanceCredentialPropertiesState(in *servicecatalog.ServiceInstanceCredentialPropertiesState, out *ServiceInstanceCredentialPropertiesState, s conversion.Scope) error { + out.Parameters = (*runtime.RawExtension)(unsafe.Pointer(in.Parameters)) + out.ParametersChecksum = in.ParametersChecksum + out.UserInfo = (*UserInfo)(unsafe.Pointer(in.UserInfo)) + return nil +} + +// Convert_servicecatalog_ServiceInstanceCredentialPropertiesState_To_v1alpha1_ServiceInstanceCredentialPropertiesState is an autogenerated conversion function. +func Convert_servicecatalog_ServiceInstanceCredentialPropertiesState_To_v1alpha1_ServiceInstanceCredentialPropertiesState(in *servicecatalog.ServiceInstanceCredentialPropertiesState, out *ServiceInstanceCredentialPropertiesState, s conversion.Scope) error { + return autoConvert_servicecatalog_ServiceInstanceCredentialPropertiesState_To_v1alpha1_ServiceInstanceCredentialPropertiesState(in, out, s) +} + func autoConvert_v1alpha1_ServiceInstanceCredentialSpec_To_servicecatalog_ServiceInstanceCredentialSpec(in *ServiceInstanceCredentialSpec, out *servicecatalog.ServiceInstanceCredentialSpec, s conversion.Scope) error { out.ServiceInstanceRef = in.ServiceInstanceRef out.Parameters = (*runtime.RawExtension)(unsafe.Pointer(in.Parameters)) @@ -615,6 +643,8 @@ func autoConvert_v1alpha1_ServiceInstanceCredentialStatus_To_servicecatalog_Serv out.CurrentOperation = servicecatalog.ServiceInstanceCredentialOperation(in.CurrentOperation) out.ReconciledGeneration = in.ReconciledGeneration out.OperationStartTime = (*meta_v1.Time)(unsafe.Pointer(in.OperationStartTime)) + out.InProgressProperties = (*servicecatalog.ServiceInstanceCredentialPropertiesState)(unsafe.Pointer(in.InProgressProperties)) + out.ExternalProperties = (*servicecatalog.ServiceInstanceCredentialPropertiesState)(unsafe.Pointer(in.ExternalProperties)) return nil } @@ -632,6 +662,8 @@ func autoConvert_servicecatalog_ServiceInstanceCredentialStatus_To_v1alpha1_Serv out.CurrentOperation = ServiceInstanceCredentialOperation(in.CurrentOperation) out.ReconciledGeneration = in.ReconciledGeneration out.OperationStartTime = (*meta_v1.Time)(unsafe.Pointer(in.OperationStartTime)) + out.InProgressProperties = (*ServiceInstanceCredentialPropertiesState)(unsafe.Pointer(in.InProgressProperties)) + out.ExternalProperties = (*ServiceInstanceCredentialPropertiesState)(unsafe.Pointer(in.ExternalProperties)) return nil } @@ -666,6 +698,32 @@ func Convert_servicecatalog_ServiceInstanceList_To_v1alpha1_ServiceInstanceList( return autoConvert_servicecatalog_ServiceInstanceList_To_v1alpha1_ServiceInstanceList(in, out, s) } +func autoConvert_v1alpha1_ServiceInstancePropertiesState_To_servicecatalog_ServiceInstancePropertiesState(in *ServiceInstancePropertiesState, out *servicecatalog.ServiceInstancePropertiesState, s conversion.Scope) error { + out.PlanName = in.PlanName + out.Parameters = (*runtime.RawExtension)(unsafe.Pointer(in.Parameters)) + out.ParametersChecksum = in.ParametersChecksum + out.UserInfo = (*servicecatalog.UserInfo)(unsafe.Pointer(in.UserInfo)) + return nil +} + +// Convert_v1alpha1_ServiceInstancePropertiesState_To_servicecatalog_ServiceInstancePropertiesState is an autogenerated conversion function. +func Convert_v1alpha1_ServiceInstancePropertiesState_To_servicecatalog_ServiceInstancePropertiesState(in *ServiceInstancePropertiesState, out *servicecatalog.ServiceInstancePropertiesState, s conversion.Scope) error { + return autoConvert_v1alpha1_ServiceInstancePropertiesState_To_servicecatalog_ServiceInstancePropertiesState(in, out, s) +} + +func autoConvert_servicecatalog_ServiceInstancePropertiesState_To_v1alpha1_ServiceInstancePropertiesState(in *servicecatalog.ServiceInstancePropertiesState, out *ServiceInstancePropertiesState, s conversion.Scope) error { + out.PlanName = in.PlanName + out.Parameters = (*runtime.RawExtension)(unsafe.Pointer(in.Parameters)) + out.ParametersChecksum = in.ParametersChecksum + out.UserInfo = (*UserInfo)(unsafe.Pointer(in.UserInfo)) + return nil +} + +// Convert_servicecatalog_ServiceInstancePropertiesState_To_v1alpha1_ServiceInstancePropertiesState is an autogenerated conversion function. +func Convert_servicecatalog_ServiceInstancePropertiesState_To_v1alpha1_ServiceInstancePropertiesState(in *servicecatalog.ServiceInstancePropertiesState, out *ServiceInstancePropertiesState, s conversion.Scope) error { + return autoConvert_servicecatalog_ServiceInstancePropertiesState_To_v1alpha1_ServiceInstancePropertiesState(in, out, s) +} + func autoConvert_v1alpha1_ServiceInstanceSpec_To_servicecatalog_ServiceInstanceSpec(in *ServiceInstanceSpec, out *servicecatalog.ServiceInstanceSpec, s conversion.Scope) error { out.ServiceClassName = in.ServiceClassName out.PlanName = in.PlanName @@ -704,6 +762,8 @@ func autoConvert_v1alpha1_ServiceInstanceStatus_To_servicecatalog_ServiceInstanc out.CurrentOperation = servicecatalog.ServiceInstanceOperation(in.CurrentOperation) out.ReconciledGeneration = in.ReconciledGeneration out.OperationStartTime = (*meta_v1.Time)(unsafe.Pointer(in.OperationStartTime)) + out.InProgressProperties = (*servicecatalog.ServiceInstancePropertiesState)(unsafe.Pointer(in.InProgressProperties)) + out.ExternalProperties = (*servicecatalog.ServiceInstancePropertiesState)(unsafe.Pointer(in.ExternalProperties)) return nil } @@ -724,6 +784,8 @@ func autoConvert_servicecatalog_ServiceInstanceStatus_To_v1alpha1_ServiceInstanc out.CurrentOperation = ServiceInstanceOperation(in.CurrentOperation) out.ReconciledGeneration = in.ReconciledGeneration out.OperationStartTime = (*meta_v1.Time)(unsafe.Pointer(in.OperationStartTime)) + out.InProgressProperties = (*ServiceInstancePropertiesState)(unsafe.Pointer(in.InProgressProperties)) + out.ExternalProperties = (*ServiceInstancePropertiesState)(unsafe.Pointer(in.ExternalProperties)) return nil } diff --git a/pkg/apis/servicecatalog/v1alpha1/zz_generated.deepcopy.go b/pkg/apis/servicecatalog/v1alpha1/zz_generated.deepcopy.go index 203159da79d..0207ae45a2b 100644 --- a/pkg/apis/servicecatalog/v1alpha1/zz_generated.deepcopy.go +++ b/pkg/apis/servicecatalog/v1alpha1/zz_generated.deepcopy.go @@ -54,9 +54,11 @@ func RegisterDeepCopies(scheme *runtime.Scheme) error { conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1alpha1_ServiceInstanceCredential, InType: reflect.TypeOf(&ServiceInstanceCredential{})}, conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1alpha1_ServiceInstanceCredentialCondition, InType: reflect.TypeOf(&ServiceInstanceCredentialCondition{})}, conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1alpha1_ServiceInstanceCredentialList, InType: reflect.TypeOf(&ServiceInstanceCredentialList{})}, + conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1alpha1_ServiceInstanceCredentialPropertiesState, InType: reflect.TypeOf(&ServiceInstanceCredentialPropertiesState{})}, conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1alpha1_ServiceInstanceCredentialSpec, InType: reflect.TypeOf(&ServiceInstanceCredentialSpec{})}, conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1alpha1_ServiceInstanceCredentialStatus, InType: reflect.TypeOf(&ServiceInstanceCredentialStatus{})}, conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1alpha1_ServiceInstanceList, InType: reflect.TypeOf(&ServiceInstanceList{})}, + conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1alpha1_ServiceInstancePropertiesState, InType: reflect.TypeOf(&ServiceInstancePropertiesState{})}, conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1alpha1_ServiceInstanceSpec, InType: reflect.TypeOf(&ServiceInstanceSpec{})}, conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1alpha1_ServiceInstanceStatus, InType: reflect.TypeOf(&ServiceInstanceStatus{})}, conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1alpha1_ServicePlan, InType: reflect.TypeOf(&ServicePlan{})}, @@ -400,6 +402,31 @@ func DeepCopy_v1alpha1_ServiceInstanceCredentialList(in interface{}, out interfa } } +// DeepCopy_v1alpha1_ServiceInstanceCredentialPropertiesState is an autogenerated deepcopy function. +func DeepCopy_v1alpha1_ServiceInstanceCredentialPropertiesState(in interface{}, out interface{}, c *conversion.Cloner) error { + { + in := in.(*ServiceInstanceCredentialPropertiesState) + out := out.(*ServiceInstanceCredentialPropertiesState) + *out = *in + if in.Parameters != nil { + in, out := &in.Parameters, &out.Parameters + if newVal, err := c.DeepCopy(*in); err != nil { + return err + } else { + *out = newVal.(*runtime.RawExtension) + } + } + if in.UserInfo != nil { + in, out := &in.UserInfo, &out.UserInfo + *out = new(UserInfo) + if err := DeepCopy_v1alpha1_UserInfo(*in, *out, c); err != nil { + return err + } + } + return nil + } +} + // DeepCopy_v1alpha1_ServiceInstanceCredentialSpec is an autogenerated deepcopy function. func DeepCopy_v1alpha1_ServiceInstanceCredentialSpec(in interface{}, out interface{}, c *conversion.Cloner) error { { @@ -454,6 +481,20 @@ func DeepCopy_v1alpha1_ServiceInstanceCredentialStatus(in interface{}, out inter *out = new(meta_v1.Time) **out = (*in).DeepCopy() } + if in.InProgressProperties != nil { + in, out := &in.InProgressProperties, &out.InProgressProperties + *out = new(ServiceInstanceCredentialPropertiesState) + if err := DeepCopy_v1alpha1_ServiceInstanceCredentialPropertiesState(*in, *out, c); err != nil { + return err + } + } + if in.ExternalProperties != nil { + in, out := &in.ExternalProperties, &out.ExternalProperties + *out = new(ServiceInstanceCredentialPropertiesState) + if err := DeepCopy_v1alpha1_ServiceInstanceCredentialPropertiesState(*in, *out, c); err != nil { + return err + } + } return nil } } @@ -477,6 +518,31 @@ func DeepCopy_v1alpha1_ServiceInstanceList(in interface{}, out interface{}, c *c } } +// DeepCopy_v1alpha1_ServiceInstancePropertiesState is an autogenerated deepcopy function. +func DeepCopy_v1alpha1_ServiceInstancePropertiesState(in interface{}, out interface{}, c *conversion.Cloner) error { + { + in := in.(*ServiceInstancePropertiesState) + out := out.(*ServiceInstancePropertiesState) + *out = *in + if in.Parameters != nil { + in, out := &in.Parameters, &out.Parameters + if newVal, err := c.DeepCopy(*in); err != nil { + return err + } else { + *out = newVal.(*runtime.RawExtension) + } + } + if in.UserInfo != nil { + in, out := &in.UserInfo, &out.UserInfo + *out = new(UserInfo) + if err := DeepCopy_v1alpha1_UserInfo(*in, *out, c); err != nil { + return err + } + } + return nil + } +} + // DeepCopy_v1alpha1_ServiceInstanceSpec is an autogenerated deepcopy function. func DeepCopy_v1alpha1_ServiceInstanceSpec(in interface{}, out interface{}, c *conversion.Cloner) error { { @@ -541,6 +607,20 @@ func DeepCopy_v1alpha1_ServiceInstanceStatus(in interface{}, out interface{}, c *out = new(meta_v1.Time) **out = (*in).DeepCopy() } + if in.InProgressProperties != nil { + in, out := &in.InProgressProperties, &out.InProgressProperties + *out = new(ServiceInstancePropertiesState) + if err := DeepCopy_v1alpha1_ServiceInstancePropertiesState(*in, *out, c); err != nil { + return err + } + } + if in.ExternalProperties != nil { + in, out := &in.ExternalProperties, &out.ExternalProperties + *out = new(ServiceInstancePropertiesState) + if err := DeepCopy_v1alpha1_ServiceInstancePropertiesState(*in, *out, c); err != nil { + return err + } + } return nil } } diff --git a/pkg/apis/servicecatalog/validation/binding.go b/pkg/apis/servicecatalog/validation/binding.go index 5612cce03de..f3c88fc5733 100644 --- a/pkg/apis/servicecatalog/validation/binding.go +++ b/pkg/apis/servicecatalog/validation/binding.go @@ -17,6 +17,7 @@ limitations under the License. package validation import ( + "github.com/ghodss/yaml" apivalidation "k8s.io/apimachinery/pkg/api/validation" "k8s.io/apimachinery/pkg/util/validation/field" @@ -26,6 +27,12 @@ import ( // validateServiceInstanceCredentialName is the validation function for ServiceInstanceCredential names. var validateServiceInstanceCredentialName = apivalidation.NameIsDNSSubdomain +var validServiceInstanceCredentialOperations = map[sc.ServiceInstanceCredentialOperation]bool{ + sc.ServiceInstanceCredentialOperation(""): true, + sc.ServiceInstanceCredentialOperationBind: true, + sc.ServiceInstanceCredentialOperationUnbind: true, +} + // ValidateServiceInstanceCredential validates a ServiceInstanceCredential and returns a list of errors. func ValidateServiceInstanceCredential(binding *sc.ServiceInstanceCredential) field.ErrorList { return internalValidateServiceInstanceCredential(binding, true) @@ -37,7 +44,12 @@ func internalValidateServiceInstanceCredential(binding *sc.ServiceInstanceCreden validateServiceInstanceCredentialName, field.NewPath("metadata"))...) allErrs = append(allErrs, validateServiceInstanceCredentialSpec(&binding.Spec, field.NewPath("Spec"), create)...) - + allErrs = append(allErrs, validateServiceInstanceCredentialStatus(&binding.Status, field.NewPath("Status"), create)...) + if binding.Status.ReconciledGeneration == binding.Generation { + if binding.Status.CurrentOperation != "" { + allErrs = append(allErrs, field.Forbidden(field.NewPath("Status").Child("currentOperation"), "currentOperation must not be present when reconciledGeneration andgeneration are the same")) + } + } return allErrs } @@ -55,6 +67,96 @@ func validateServiceInstanceCredentialSpec(spec *sc.ServiceInstanceCredentialSpe return allErrs } +func validateServiceInstanceCredentialStatus(status *sc.ServiceInstanceCredentialStatus, fldPath *field.Path, create bool) field.ErrorList { + allErrs := field.ErrorList{} + + if !validServiceInstanceCredentialOperations[status.CurrentOperation] { + validValues := make([]string, len(validServiceInstanceCredentialOperations)) + i := 0 + for operation := range validServiceInstanceCredentialOperations { + validValues[i] = string(operation) + i++ + } + allErrs = append(allErrs, field.NotSupported(fldPath.Child("currentOperation"), status.CurrentOperation, validValues)) + } + + switch status.CurrentOperation { + case sc.ServiceInstanceCredentialOperationBind, sc.ServiceInstanceCredentialOperationUnbind, "": + // Valid values + default: + allErrs = append(allErrs) + } + + if status.CurrentOperation == "" { + if status.OperationStartTime != nil { + allErrs = append(allErrs, field.Forbidden(fldPath.Child("operationStartTime"), "operationStartTime must not be present when currentOperation is not present")) + } + } else { + if status.OperationStartTime == nil { + allErrs = append(allErrs, field.Required(fldPath.Child("operationStartTime"), "operationStartTime is required when currentOperation is present")) + } + // Do not allow the binding to be ready if there is an on-going operation + for i, c := range status.Conditions { + if c.Type == sc.ServiceInstanceCredentialConditionReady && c.Status == sc.ConditionTrue { + allErrs = append(allErrs, field.Forbidden(fldPath.Child("Conditions").Index(i), "Can not set ServiceInstanceCredentialConditionReady to true when there is an operation in progress")) + } + } + } + + if status.CurrentOperation == sc.ServiceInstanceCredentialOperationBind { + if status.InProgressProperties == nil { + allErrs = append(allErrs, field.Required(fldPath.Child("inProgressProperties"), `inProgressProperties is required when currentOperation is "Bind"`)) + } + } else { + if status.InProgressProperties != nil { + allErrs = append(allErrs, field.Forbidden(fldPath.Child("inProgressProperties"), `inProgressProperties must not be present when currentOperation is not "Bind"`)) + } + } + + if status.InProgressProperties != nil { + allErrs = append(allErrs, validateServiceInstanceCredentialPropertiesState(status.InProgressProperties, fldPath.Child("inProgressProperties"), create)...) + } + + if status.ExternalProperties != nil { + allErrs = append(allErrs, validateServiceInstanceCredentialPropertiesState(status.ExternalProperties, fldPath.Child("externalProperties"), create)...) + } + + return allErrs +} + +func validateServiceInstanceCredentialPropertiesState(propertiesState *sc.ServiceInstanceCredentialPropertiesState, fldPath *field.Path, create bool) field.ErrorList { + allErrs := field.ErrorList{} + + if propertiesState.Parameters == nil { + if propertiesState.ParametersChecksum != "" { + allErrs = append(allErrs, field.Forbidden(fldPath.Child("parametersChecksum"), "parametersChecksum must be empty when there are no parameters")) + } + } else { + if len(propertiesState.Parameters.Raw) == 0 { + allErrs = append(allErrs, field.Required(fldPath.Child("parameters").Child("raw"), "raw must not be empty")) + } else { + unmarshalled := make(map[string]interface{}) + if err := yaml.Unmarshal(propertiesState.Parameters.Raw, &unmarshalled); err != nil { + allErrs = append(allErrs, field.Invalid(fldPath.Child("parameters").Child("raw"), propertiesState.Parameters.Raw, "raw must be valid yaml")) + } + } + if propertiesState.ParametersChecksum == "" { + allErrs = append(allErrs, field.Forbidden(fldPath.Child("parametersChecksum"), "parametersChecksum must not be empty when there are parameters")) + } + } + + if propertiesState.ParametersChecksum != "" { + if len(propertiesState.ParametersChecksum) != 64 { + allErrs = append(allErrs, field.Invalid(fldPath.Child("parametersChecksum"), propertiesState.ParametersChecksum, "parametersChecksum must be exactly 64 digits")) + } + if !stringIsHexadecimal(propertiesState.ParametersChecksum) { + allErrs = append(allErrs, field.Invalid(fldPath.Child("parametersChecksum"), propertiesState.ParametersChecksum, "parametersChecksum must be a hexadecimal number")) + } + } + + return allErrs +} + // internalValidateServiceInstanceCredentialUpdateAllowed ensures there is not a // pending update on-going with the spec of the binding before allowing an update // to the spec to go through. diff --git a/pkg/apis/servicecatalog/validation/binding_test.go b/pkg/apis/servicecatalog/validation/binding_test.go index c0b502e4b8c..452a67a2506 100644 --- a/pkg/apis/servicecatalog/validation/binding_test.go +++ b/pkg/apis/servicecatalog/validation/binding_test.go @@ -20,6 +20,7 @@ import ( "testing" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" "k8s.io/client-go/pkg/api/v1" "github.com/kubernetes-incubator/service-catalog/pkg/apis/servicecatalog" @@ -40,6 +41,24 @@ func validServiceInstanceCredential() *servicecatalog.ServiceInstanceCredential } } +func validServiceInstanceCredentialWithInProgressBind() *servicecatalog.ServiceInstanceCredential { + binding := validServiceInstanceCredential() + binding.Generation = 1 + binding.Status.ReconciledGeneration = 2 + binding.Status.CurrentOperation = servicecatalog.ServiceInstanceCredentialOperationBind + now := metav1.Now() + binding.Status.OperationStartTime = &now + binding.Status.InProgressProperties = validServiceInstanceCredentialPropertiesState() + return binding +} + +func validServiceInstanceCredentialPropertiesState() *servicecatalog.ServiceInstanceCredentialPropertiesState { + return &servicecatalog.ServiceInstanceCredentialPropertiesState{ + Parameters: &runtime.RawExtension{Raw: []byte("a: 1\nb: \"2\"")}, + ParametersChecksum: "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef", + } +} + func TestValidateServiceInstanceCredential(t *testing.T) { cases := []struct { name string @@ -96,6 +115,257 @@ func TestValidateServiceInstanceCredential(t *testing.T) { }(), valid: false, }, + { + name: "valid with in-progress bind", + binding: validServiceInstanceCredentialWithInProgressBind(), + valid: true, + }, + { + name: "valid with in-progress unbind", + binding: func() *servicecatalog.ServiceInstanceCredential { + b := validServiceInstanceCredentialWithInProgressBind() + b.Status.CurrentOperation = servicecatalog.ServiceInstanceCredentialOperationUnbind + b.Status.InProgressProperties = nil + return b + }(), + valid: true, + }, + { + name: "invalid current operation", + binding: func() *servicecatalog.ServiceInstanceCredential { + b := validServiceInstanceCredentialWithInProgressBind() + b.Status.CurrentOperation = servicecatalog.ServiceInstanceCredentialOperation("bad-operation") + return b + }(), + valid: false, + }, + { + name: "in-progress without updated generation", + binding: func() *servicecatalog.ServiceInstanceCredential { + b := validServiceInstanceCredentialWithInProgressBind() + b.Status.ReconciledGeneration = b.Generation + return b + }(), + valid: false, + }, + { + name: "in-progress with missing OperationStartTime", + binding: func() *servicecatalog.ServiceInstanceCredential { + b := validServiceInstanceCredentialWithInProgressBind() + b.Status.OperationStartTime = nil + return b + }(), + valid: false, + }, + { + name: "not in-progress with present OperationStartTime", + binding: func() *servicecatalog.ServiceInstanceCredential { + b := validServiceInstanceCredential() + now := metav1.Now() + b.Status.OperationStartTime = &now + return b + }(), + valid: false, + }, + { + name: "in-progress with condition ready/true", + binding: func() *servicecatalog.ServiceInstanceCredential { + b := validServiceInstanceCredentialWithInProgressBind() + b.Status.Conditions = []servicecatalog.ServiceInstanceCredentialCondition{ + { + Type: servicecatalog.ServiceInstanceCredentialConditionReady, + Status: servicecatalog.ConditionTrue, + }, + } + return b + }(), + valid: false, + }, + { + name: "in-progress with condition ready/false", + binding: func() *servicecatalog.ServiceInstanceCredential { + b := validServiceInstanceCredentialWithInProgressBind() + b.Status.Conditions = []servicecatalog.ServiceInstanceCredentialCondition{ + { + Type: servicecatalog.ServiceInstanceCredentialConditionReady, + Status: servicecatalog.ConditionFalse, + }, + } + return b + }(), + valid: true, + }, + { + name: "in-progress bind with missing InProgressParameters", + binding: func() *servicecatalog.ServiceInstanceCredential { + b := validServiceInstanceCredentialWithInProgressBind() + b.Status.InProgressProperties = nil + return b + }(), + valid: false, + }, + { + name: "not in-progress with present InProgressParameters", + binding: func() *servicecatalog.ServiceInstanceCredential { + b := validServiceInstanceCredential() + b.Status.InProgressProperties = validServiceInstanceCredentialPropertiesState() + return b + }(), + valid: false, + }, + { + name: "in-progress unbind with present InProgressParameters", + binding: func() *servicecatalog.ServiceInstanceCredential { + b := validServiceInstanceCredentialWithInProgressBind() + b.Status.CurrentOperation = servicecatalog.ServiceInstanceCredentialOperationUnbind + return b + }(), + valid: false, + }, + { + name: "valid in-progress properties with no parameters", + binding: func() *servicecatalog.ServiceInstanceCredential { + b := validServiceInstanceCredentialWithInProgressBind() + b.Status.InProgressProperties.Parameters = nil + b.Status.InProgressProperties.ParametersChecksum = "" + return b + }(), + valid: true, + }, + { + name: "in-progress properties parameters with missing parameters checksum", + binding: func() *servicecatalog.ServiceInstanceCredential { + b := validServiceInstanceCredentialWithInProgressBind() + b.Status.InProgressProperties.ParametersChecksum = "" + return b + }(), + valid: false, + }, + { + name: "in-progress properties parameters checksum with missing parameters", + binding: func() *servicecatalog.ServiceInstanceCredential { + b := validServiceInstanceCredentialWithInProgressBind() + b.Status.InProgressProperties.Parameters = nil + return b + }(), + valid: false, + }, + { + name: "in-progress properties parameters with missing raw", + binding: func() *servicecatalog.ServiceInstanceCredential { + b := validServiceInstanceCredentialWithInProgressBind() + b.Status.InProgressProperties.Parameters.Raw = []byte{} + return b + }(), + valid: false, + }, + { + name: "in-progress properties parameters with malformed yaml", + binding: func() *servicecatalog.ServiceInstanceCredential { + b := validServiceInstanceCredentialWithInProgressBind() + b.Status.InProgressProperties.Parameters.Raw = []byte("bad yaml") + return b + }(), + valid: false, + }, + { + name: "in-progress properties parameters checksum too small", + binding: func() *servicecatalog.ServiceInstanceCredential { + b := validServiceInstanceCredentialWithInProgressBind() + b.Status.InProgressProperties.ParametersChecksum = "0123456" + return b + }(), + valid: false, + }, + { + name: "in-progress properties parameters checksum malformed", + binding: func() *servicecatalog.ServiceInstanceCredential { + b := validServiceInstanceCredentialWithInProgressBind() + b.Status.InProgressProperties.ParametersChecksum = "not hex" + return b + }(), + valid: false, + }, + { + name: "valid external properties", + binding: func() *servicecatalog.ServiceInstanceCredential { + b := validServiceInstanceCredential() + b.Status.ExternalProperties = validServiceInstanceCredentialPropertiesState() + return b + }(), + valid: true, + }, + { + name: "valid external properties with no parameters", + binding: func() *servicecatalog.ServiceInstanceCredential { + b := validServiceInstanceCredential() + b.Status.ExternalProperties = validServiceInstanceCredentialPropertiesState() + b.Status.ExternalProperties.Parameters = nil + b.Status.ExternalProperties.ParametersChecksum = "" + return b + }(), + valid: true, + }, + { + name: "external properties parameters with missing parameters checksum", + binding: func() *servicecatalog.ServiceInstanceCredential { + b := validServiceInstanceCredential() + b.Status.ExternalProperties = validServiceInstanceCredentialPropertiesState() + b.Status.ExternalProperties.ParametersChecksum = "" + return b + }(), + valid: false, + }, + { + name: "external properties parameters checksum with missing parameters", + binding: func() *servicecatalog.ServiceInstanceCredential { + b := validServiceInstanceCredential() + b.Status.ExternalProperties = validServiceInstanceCredentialPropertiesState() + b.Status.ExternalProperties.Parameters = nil + return b + }(), + valid: false, + }, + { + name: "external properties parameters with missing raw", + binding: func() *servicecatalog.ServiceInstanceCredential { + b := validServiceInstanceCredential() + b.Status.ExternalProperties = validServiceInstanceCredentialPropertiesState() + b.Status.ExternalProperties.Parameters.Raw = []byte{} + return b + }(), + valid: false, + }, + { + name: "external properties parameters with malformed yaml", + binding: func() *servicecatalog.ServiceInstanceCredential { + b := validServiceInstanceCredential() + b.Status.ExternalProperties = validServiceInstanceCredentialPropertiesState() + b.Status.ExternalProperties.Parameters.Raw = []byte("bad yaml") + return b + }(), + valid: false, + }, + { + name: "external properties parameters checksum too small", + binding: func() *servicecatalog.ServiceInstanceCredential { + b := validServiceInstanceCredential() + b.Status.ExternalProperties = validServiceInstanceCredentialPropertiesState() + b.Status.ExternalProperties.ParametersChecksum = "0123456" + return b + }(), + valid: false, + }, + { + name: "external properties parameters checksum malformed", + binding: func() *servicecatalog.ServiceInstanceCredential { + b := validServiceInstanceCredential() + b.Status.ExternalProperties = validServiceInstanceCredentialPropertiesState() + b.Status.ExternalProperties.ParametersChecksum = "not hex" + return b + }(), + valid: false, + }, } for _, tc := range cases { diff --git a/pkg/apis/servicecatalog/validation/instance.go b/pkg/apis/servicecatalog/validation/instance.go index a28072f8c0e..2f86032f495 100644 --- a/pkg/apis/servicecatalog/validation/instance.go +++ b/pkg/apis/servicecatalog/validation/instance.go @@ -17,6 +17,7 @@ limitations under the License. package validation import ( + "github.com/ghodss/yaml" apivalidation "k8s.io/apimachinery/pkg/api/validation" "k8s.io/apimachinery/pkg/util/validation/field" @@ -27,6 +28,13 @@ import ( // validateServiceInstanceName is the validation function for Instance names. var validateServiceInstanceName = apivalidation.NameIsDNSSubdomain +var validServiceInstanceOperations = map[sc.ServiceInstanceOperation]bool{ + sc.ServiceInstanceOperation(""): true, + sc.ServiceInstanceOperationProvision: true, + sc.ServiceInstanceOperationUpdate: true, + sc.ServiceInstanceOperationDeprovision: true, +} + // ValidateServiceInstance validates an Instance and returns a list of errors. func ValidateServiceInstance(instance *sc.ServiceInstance) field.ErrorList { return internalValidateServiceInstance(instance, true) @@ -39,6 +47,11 @@ func internalValidateServiceInstance(instance *sc.ServiceInstance, create bool) field.NewPath("metadata"))...) allErrs = append(allErrs, validateServiceInstanceSpec(&instance.Spec, field.NewPath("Spec"), create)...) allErrs = append(allErrs, validateServiceInstanceStatus(&instance.Status, field.NewPath("Status"), create)...) + if instance.Status.ReconciledGeneration == instance.Generation { + if instance.Status.CurrentOperation != "" { + allErrs = append(allErrs, field.Forbidden(field.NewPath("Status").Child("currentOperation"), "currentOperation must not be present when reconciledGeneration and generation are the same")) + } + } return allErrs } @@ -87,22 +100,94 @@ func validateServiceInstanceSpec(spec *sc.ServiceInstanceSpec, fldPath *field.Pa return allErrs } -func validateServiceInstanceStatus(spec *sc.ServiceInstanceStatus, fldPath *field.Path, create bool) field.ErrorList { - errors := field.ErrorList{} - // TODO(vaikas): Implement more comprehensive status validation. - // https://github.com/kubernetes-incubator/service-catalog/issues/882 +func validateServiceInstanceStatus(status *sc.ServiceInstanceStatus, fldPath *field.Path, create bool) field.ErrorList { + allErrs := field.ErrorList{} - // Do not allow the instance to be ready if an async operation is ongoing - // ongoing - if spec.AsyncOpInProgress { - for _, c := range spec.Conditions { + if !validServiceInstanceOperations[status.CurrentOperation] { + validValues := make([]string, len(validServiceInstanceOperations)) + i := 0 + for operation := range validServiceInstanceOperations { + validValues[i] = string(operation) + i++ + } + allErrs = append(allErrs, field.NotSupported(fldPath.Child("currentOperation"), status.CurrentOperation, validValues)) + } + + if status.CurrentOperation == "" { + if status.OperationStartTime != nil { + allErrs = append(allErrs, field.Forbidden(fldPath.Child("operationStartTime"), "operationStartTime must not be present when currentOperation is not present")) + } + if status.AsyncOpInProgress { + allErrs = append(allErrs, field.Forbidden(fldPath.Child("asyncOpInProgress"), "asyncOpInProgress cannot be true when there is no currentOperation")) + } + if status.LastOperation != nil { + allErrs = append(allErrs, field.Forbidden(fldPath.Child("lastOperation"), "lastOperation cannot be true when currentOperation is not present")) + } + } else { + if status.OperationStartTime == nil { + allErrs = append(allErrs, field.Required(fldPath.Child("operationStartTime"), "operationStartTime is required when currentOperation is present")) + } + // Do not allow the instance to be ready if there is an on-going operation + for i, c := range status.Conditions { if c.Type == sc.ServiceInstanceConditionReady && c.Status == sc.ConditionTrue { - errors = append(errors, field.Forbidden(fldPath.Child("Conditions"), "Can not set ServiceInstanceConditionReady to true when an async operation is in progress")) + allErrs = append(allErrs, field.Forbidden(fldPath.Child("Conditions").Index(i), "Can not set ServiceInstanceConditionReady to true when there is an operation in progress")) } } } - return errors + switch status.CurrentOperation { + case sc.ServiceInstanceOperationProvision, sc.ServiceInstanceOperationUpdate: + if status.InProgressProperties == nil { + allErrs = append(allErrs, field.Required(fldPath.Child("inProgressProperties"), `inProgressProperties is required when currentOperation is "Provision" or "Update"`)) + } + default: + if status.InProgressProperties != nil { + allErrs = append(allErrs, field.Forbidden(fldPath.Child("inProgressProperties"), `inProgressProperties must not be present when currentOperation is neither "Provision" nor "Update"`)) + } + } + + if status.InProgressProperties != nil { + allErrs = append(allErrs, validateServiceInstancePropertiesState(status.InProgressProperties, fldPath.Child("inProgressProperties"), create)...) + } + + if status.ExternalProperties != nil { + allErrs = append(allErrs, validateServiceInstancePropertiesState(status.ExternalProperties, fldPath.Child("externalProperties"), create)...) + } + + return allErrs +} + +func validateServiceInstancePropertiesState(propertiesState *sc.ServiceInstancePropertiesState, fldPath *field.Path, create bool) field.ErrorList { + allErrs := field.ErrorList{} + + if propertiesState.Parameters == nil { + if propertiesState.ParametersChecksum != "" { + allErrs = append(allErrs, field.Forbidden(fldPath.Child("parametersChecksum"), "parametersChecksum must be empty when there are no parameters")) + } + } else { + if len(propertiesState.Parameters.Raw) == 0 { + allErrs = append(allErrs, field.Required(fldPath.Child("parameters").Child("raw"), "raw must not be empty")) + } else { + unmarshalled := make(map[string]interface{}) + if err := yaml.Unmarshal(propertiesState.Parameters.Raw, &unmarshalled); err != nil { + allErrs = append(allErrs, field.Invalid(fldPath.Child("parameters").Child("raw"), propertiesState.Parameters.Raw, "raw must be valid yaml")) + } + } + if propertiesState.ParametersChecksum == "" { + allErrs = append(allErrs, field.Forbidden(fldPath.Child("parametersChecksum"), "parametersChecksum must not be empty when there are parameters")) + } + } + + if propertiesState.ParametersChecksum != "" { + if len(propertiesState.ParametersChecksum) != 64 { + allErrs = append(allErrs, field.Invalid(fldPath.Child("parametersChecksum"), propertiesState.ParametersChecksum, "parametersChecksum must be exactly 64 digits")) + } + if !stringIsHexadecimal(propertiesState.ParametersChecksum) { + allErrs = append(allErrs, field.Invalid(fldPath.Child("parametersChecksum"), propertiesState.ParametersChecksum, "parametersChecksum must be a hexadecimal number")) + } + } + + return allErrs } // internalValidateServiceInstanceUpdateAllowed ensures there is not a diff --git a/pkg/apis/servicecatalog/validation/instance_test.go b/pkg/apis/servicecatalog/validation/instance_test.go index 5ddd3cf0df7..b9b688f814a 100644 --- a/pkg/apis/servicecatalog/validation/instance_test.go +++ b/pkg/apis/servicecatalog/validation/instance_test.go @@ -21,10 +21,42 @@ import ( "testing" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" "github.com/kubernetes-incubator/service-catalog/pkg/apis/servicecatalog" ) +func validServiceInstance() *servicecatalog.ServiceInstance { + return &servicecatalog.ServiceInstance{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-instance", + Namespace: "test-ns", + }, + Spec: servicecatalog.ServiceInstanceSpec{ + ServiceClassName: "test-serviceclass", + PlanName: "test-plan", + }, + } +} + +func validServiceInstanceWithInProgressProvision() *servicecatalog.ServiceInstance { + instance := validServiceInstance() + instance.Generation = 1 + instance.Status.ReconciledGeneration = 2 + instance.Status.CurrentOperation = servicecatalog.ServiceInstanceOperationProvision + now := metav1.Now() + instance.Status.OperationStartTime = &now + instance.Status.InProgressProperties = validServiceInstancePropertiesState() + return instance +} + +func validServiceInstancePropertiesState() *servicecatalog.ServiceInstancePropertiesState { + return &servicecatalog.ServiceInstancePropertiesState{ + Parameters: &runtime.RawExtension{Raw: []byte("a: 1\nb: \"2\"")}, + ParametersChecksum: "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef", + } +} + func TestValidateServiceInstance(t *testing.T) { cases := []struct { name string @@ -32,84 +64,323 @@ func TestValidateServiceInstance(t *testing.T) { valid bool }{ { - name: "valid", - instance: &servicecatalog.ServiceInstance{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-instance", - Namespace: "test-ns", - }, - Spec: servicecatalog.ServiceInstanceSpec{ - ServiceClassName: "test-serviceclass", - PlanName: "test-plan", - }, - }, - valid: true, + name: "valid", + instance: validServiceInstance(), + valid: true, }, { name: "missing namespace", - instance: &servicecatalog.ServiceInstance{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-instance", - }, - Spec: servicecatalog.ServiceInstanceSpec{ - ServiceClassName: "test-serviceclass", - PlanName: "test-plan", - }, - }, + instance: func() *servicecatalog.ServiceInstance { + i := validServiceInstance() + i.Namespace = "" + return i + }(), valid: false, }, { name: "missing serviceClassName", - instance: &servicecatalog.ServiceInstance{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-instance", - Namespace: "test-ns", - }, - Spec: servicecatalog.ServiceInstanceSpec{ - PlanName: "test-plan", - }, - }, + instance: func() *servicecatalog.ServiceInstance { + i := validServiceInstance() + i.Spec.ServiceClassName = "" + return i + }(), valid: false, }, { name: "invalid serviceClassName", - instance: &servicecatalog.ServiceInstance{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-instance", - Namespace: "test-ns", - }, - Spec: servicecatalog.ServiceInstanceSpec{ - ServiceClassName: "oing20&)*^&", - PlanName: "test-plan", - }, - }, + instance: func() *servicecatalog.ServiceInstance { + i := validServiceInstance() + i.Spec.ServiceClassName = "oing20&)*^&" + return i + }(), valid: false, }, { name: "missing planName", - instance: &servicecatalog.ServiceInstance{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-instance", - Namespace: "test-ns", - }, - Spec: servicecatalog.ServiceInstanceSpec{ - ServiceClassName: "test-serviceclass", - }, - }, + instance: func() *servicecatalog.ServiceInstance { + i := validServiceInstance() + i.Spec.PlanName = "" + return i + }(), valid: false, }, { name: "invalid planName", - instance: &servicecatalog.ServiceInstance{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-instance", - Namespace: "test-ns", - }, - Spec: servicecatalog.ServiceInstanceSpec{ - ServiceClassName: "test-serviceclass", - PlanName: "9651.JVHbebe", - }, - }, + instance: func() *servicecatalog.ServiceInstance { + i := validServiceInstance() + i.Spec.PlanName = "9651.JVHbebe" + return i + }(), + valid: false, + }, + { + name: "valid with in-progress provision", + instance: validServiceInstanceWithInProgressProvision(), + valid: true, + }, + { + name: "valid with in-progress update", + instance: func() *servicecatalog.ServiceInstance { + i := validServiceInstanceWithInProgressProvision() + i.Status.CurrentOperation = servicecatalog.ServiceInstanceOperationUpdate + return i + }(), + valid: true, + }, + { + name: "valid with in-progress deprovision", + instance: func() *servicecatalog.ServiceInstance { + i := validServiceInstanceWithInProgressProvision() + i.Status.CurrentOperation = servicecatalog.ServiceInstanceOperationDeprovision + i.Status.InProgressProperties = nil + return i + }(), + valid: true, + }, + { + name: "invalid current operation", + instance: func() *servicecatalog.ServiceInstance { + i := validServiceInstanceWithInProgressProvision() + i.Status.CurrentOperation = servicecatalog.ServiceInstanceOperation("bad-operation") + return i + }(), + valid: false, + }, + { + name: "in-progress without updated generation", + instance: func() *servicecatalog.ServiceInstance { + i := validServiceInstanceWithInProgressProvision() + i.Status.ReconciledGeneration = i.Generation + return i + }(), + valid: false, + }, + { + name: "in-progress with missing OperationStartTime", + instance: func() *servicecatalog.ServiceInstance { + i := validServiceInstanceWithInProgressProvision() + i.Status.OperationStartTime = nil + return i + }(), + valid: false, + }, + { + name: "not in-progress with present OperationStartTime", + instance: func() *servicecatalog.ServiceInstance { + i := validServiceInstance() + now := metav1.Now() + i.Status.OperationStartTime = &now + return i + }(), + valid: false, + }, + { + name: "in-progress with condition ready/true", + instance: func() *servicecatalog.ServiceInstance { + i := validServiceInstanceWithInProgressProvision() + i.Status.Conditions = []servicecatalog.ServiceInstanceCondition{ + { + Type: servicecatalog.ServiceInstanceConditionReady, + Status: servicecatalog.ConditionTrue, + }, + } + return i + }(), + valid: false, + }, + { + name: "in-progress with condition ready/false", + instance: func() *servicecatalog.ServiceInstance { + i := validServiceInstanceWithInProgressProvision() + i.Status.Conditions = []servicecatalog.ServiceInstanceCondition{ + { + Type: servicecatalog.ServiceInstanceConditionReady, + Status: servicecatalog.ConditionFalse, + }, + } + return i + }(), + valid: true, + }, + { + name: "in-progress provision with missing InProgressParameters", + instance: func() *servicecatalog.ServiceInstance { + i := validServiceInstanceWithInProgressProvision() + i.Status.InProgressProperties = nil + return i + }(), + valid: false, + }, + { + name: "in-progress update with missing InProgressParameters", + instance: func() *servicecatalog.ServiceInstance { + i := validServiceInstanceWithInProgressProvision() + i.Status.CurrentOperation = servicecatalog.ServiceInstanceOperationUpdate + i.Status.InProgressProperties = nil + return i + }(), + valid: false, + }, + { + name: "not in-progress with present InProgressParameters", + instance: func() *servicecatalog.ServiceInstance { + i := validServiceInstance() + i.Status.InProgressProperties = validServiceInstancePropertiesState() + return i + }(), + valid: false, + }, + { + name: "in-progress deprovision with present InProgressParameters", + instance: func() *servicecatalog.ServiceInstance { + i := validServiceInstanceWithInProgressProvision() + i.Status.CurrentOperation = servicecatalog.ServiceInstanceOperationDeprovision + return i + }(), + valid: false, + }, + { + name: "valid in-progress properties with no parameters", + instance: func() *servicecatalog.ServiceInstance { + i := validServiceInstanceWithInProgressProvision() + i.Status.InProgressProperties.Parameters = nil + i.Status.InProgressProperties.ParametersChecksum = "" + return i + }(), + valid: true, + }, + { + name: "in-progress properties parameters with missing parameters checksum", + instance: func() *servicecatalog.ServiceInstance { + i := validServiceInstanceWithInProgressProvision() + i.Status.InProgressProperties.ParametersChecksum = "" + return i + }(), + valid: false, + }, + { + name: "in-progress properties parameters checksum with missing parameters", + instance: func() *servicecatalog.ServiceInstance { + i := validServiceInstanceWithInProgressProvision() + i.Status.InProgressProperties.Parameters = nil + return i + }(), + valid: false, + }, + { + name: "in-progress properties parameters with missing raw", + instance: func() *servicecatalog.ServiceInstance { + i := validServiceInstanceWithInProgressProvision() + i.Status.InProgressProperties.Parameters.Raw = []byte{} + return i + }(), + valid: false, + }, + { + name: "in-progress properties parameters with malformed yaml", + instance: func() *servicecatalog.ServiceInstance { + i := validServiceInstanceWithInProgressProvision() + i.Status.InProgressProperties.Parameters.Raw = []byte("bad yaml") + return i + }(), + valid: false, + }, + { + name: "in-progress properties parameters checksum too small", + instance: func() *servicecatalog.ServiceInstance { + i := validServiceInstanceWithInProgressProvision() + i.Status.InProgressProperties.ParametersChecksum = "0123456" + return i + }(), + valid: false, + }, + { + name: "in-progress properties parameters checksum malformed", + instance: func() *servicecatalog.ServiceInstance { + i := validServiceInstanceWithInProgressProvision() + i.Status.InProgressProperties.ParametersChecksum = "not hex" + return i + }(), + valid: false, + }, + { + name: "valid external properties", + instance: func() *servicecatalog.ServiceInstance { + i := validServiceInstance() + i.Status.ExternalProperties = validServiceInstancePropertiesState() + return i + }(), + valid: true, + }, + { + name: "valid external properties with no parameters", + instance: func() *servicecatalog.ServiceInstance { + i := validServiceInstance() + i.Status.ExternalProperties = validServiceInstancePropertiesState() + i.Status.ExternalProperties.Parameters = nil + i.Status.ExternalProperties.ParametersChecksum = "" + return i + }(), + valid: true, + }, + { + name: "external properties parameters with missing parameters checksum", + instance: func() *servicecatalog.ServiceInstance { + i := validServiceInstance() + i.Status.ExternalProperties = validServiceInstancePropertiesState() + i.Status.ExternalProperties.ParametersChecksum = "" + return i + }(), + valid: false, + }, + { + name: "external properties parameters checksum with missing parameters", + instance: func() *servicecatalog.ServiceInstance { + i := validServiceInstance() + i.Status.ExternalProperties = validServiceInstancePropertiesState() + i.Status.ExternalProperties.Parameters = nil + return i + }(), + valid: false, + }, + { + name: "external properties parameters with missing raw", + instance: func() *servicecatalog.ServiceInstance { + i := validServiceInstance() + i.Status.ExternalProperties = validServiceInstancePropertiesState() + i.Status.ExternalProperties.Parameters.Raw = []byte{} + return i + }(), + valid: false, + }, + { + name: "external properties parameters with malformed yaml", + instance: func() *servicecatalog.ServiceInstance { + i := validServiceInstance() + i.Status.ExternalProperties = validServiceInstancePropertiesState() + i.Status.ExternalProperties.Parameters.Raw = []byte("bad yaml") + return i + }(), + valid: false, + }, + { + name: "external properties parameters checksum too small", + instance: func() *servicecatalog.ServiceInstance { + i := validServiceInstance() + i.Status.ExternalProperties = validServiceInstancePropertiesState() + i.Status.ExternalProperties.ParametersChecksum = "0123456" + return i + }(), + valid: false, + }, + { + name: "external properties parameters checksum malformed", + instance: func() *servicecatalog.ServiceInstance { + i := validServiceInstance() + i.Status.ExternalProperties = validServiceInstancePropertiesState() + i.Status.ExternalProperties.ParametersChecksum = "not hex" + return i + }(), valid: false, }, } @@ -204,6 +475,7 @@ func TestInternalValidateServiceInstanceUpdateAllowed(t *testing.T) { } func TestValidateServiceInstanceStatusUpdate(t *testing.T) { + now := metav1.Now() cases := []struct { name string old *servicecatalog.ServiceInstanceStatus @@ -217,7 +489,10 @@ func TestValidateServiceInstanceStatusUpdate(t *testing.T) { AsyncOpInProgress: false, }, new: &servicecatalog.ServiceInstanceStatus{ - AsyncOpInProgress: true, + CurrentOperation: servicecatalog.ServiceInstanceOperationProvision, + OperationStartTime: &now, + InProgressProperties: &servicecatalog.ServiceInstancePropertiesState{}, + AsyncOpInProgress: true, }, valid: true, err: "", @@ -225,7 +500,10 @@ func TestValidateServiceInstanceStatusUpdate(t *testing.T) { { name: "Complete async op", old: &servicecatalog.ServiceInstanceStatus{ - AsyncOpInProgress: true, + CurrentOperation: servicecatalog.ServiceInstanceOperationProvision, + OperationStartTime: &now, + InProgressProperties: &servicecatalog.ServiceInstancePropertiesState{}, + AsyncOpInProgress: true, }, new: &servicecatalog.ServiceInstanceStatus{ AsyncOpInProgress: false, @@ -234,35 +512,39 @@ func TestValidateServiceInstanceStatusUpdate(t *testing.T) { err: "", }, { - name: "ServiceInstanceConditionReady can not be true if async is ongoing", + name: "ServiceInstanceConditionReady can not be true if operation is ongoing", old: &servicecatalog.ServiceInstanceStatus{ - AsyncOpInProgress: true, + CurrentOperation: "", Conditions: []servicecatalog.ServiceInstanceCondition{{ Type: servicecatalog.ServiceInstanceConditionReady, Status: servicecatalog.ConditionFalse, }}, }, new: &servicecatalog.ServiceInstanceStatus{ - AsyncOpInProgress: true, + CurrentOperation: servicecatalog.ServiceInstanceOperationProvision, + OperationStartTime: &now, + InProgressProperties: &servicecatalog.ServiceInstancePropertiesState{}, Conditions: []servicecatalog.ServiceInstanceCondition{{ Type: servicecatalog.ServiceInstanceConditionReady, Status: servicecatalog.ConditionTrue, }}, }, valid: false, - err: "async operation is in progress", + err: "operation in progress", }, { - name: "ServiceInstanceConditionReady can be true if async is completed", + name: "ServiceInstanceConditionReady can be true if operation is completed", old: &servicecatalog.ServiceInstanceStatus{ - AsyncOpInProgress: true, + CurrentOperation: servicecatalog.ServiceInstanceOperationProvision, + OperationStartTime: &now, + InProgressProperties: &servicecatalog.ServiceInstancePropertiesState{}, Conditions: []servicecatalog.ServiceInstanceCondition{{ Type: servicecatalog.ServiceInstanceConditionReady, Status: servicecatalog.ConditionFalse, }}, }, new: &servicecatalog.ServiceInstanceStatus{ - AsyncOpInProgress: false, + CurrentOperation: "", Conditions: []servicecatalog.ServiceInstanceCondition{{ Type: servicecatalog.ServiceInstanceConditionReady, Status: servicecatalog.ConditionTrue, @@ -272,40 +554,46 @@ func TestValidateServiceInstanceStatusUpdate(t *testing.T) { err: "", }, { - name: "Update instance condition ready status during async", + name: "Update non-ready instance condition during operation", old: &servicecatalog.ServiceInstanceStatus{ - AsyncOpInProgress: true, - Conditions: []servicecatalog.ServiceInstanceCondition{{Status: servicecatalog.ConditionFalse}}, + CurrentOperation: servicecatalog.ServiceInstanceOperationProvision, + OperationStartTime: &now, + InProgressProperties: &servicecatalog.ServiceInstancePropertiesState{}, + Conditions: []servicecatalog.ServiceInstanceCondition{{Status: servicecatalog.ConditionFalse}}, }, new: &servicecatalog.ServiceInstanceStatus{ - AsyncOpInProgress: true, - Conditions: []servicecatalog.ServiceInstanceCondition{{Status: servicecatalog.ConditionTrue}}, + CurrentOperation: servicecatalog.ServiceInstanceOperationProvision, + OperationStartTime: &now, + InProgressProperties: &servicecatalog.ServiceInstancePropertiesState{}, + Conditions: []servicecatalog.ServiceInstanceCondition{{Status: servicecatalog.ConditionTrue}}, }, valid: true, err: "", }, { - name: "Update instance condition ready status during async false", + name: "Update non-ready instance condition outside of operation", old: &servicecatalog.ServiceInstanceStatus{ - AsyncOpInProgress: false, - Conditions: []servicecatalog.ServiceInstanceCondition{{Status: servicecatalog.ConditionFalse}}, + CurrentOperation: "", + Conditions: []servicecatalog.ServiceInstanceCondition{{Status: servicecatalog.ConditionFalse}}, }, new: &servicecatalog.ServiceInstanceStatus{ - AsyncOpInProgress: false, - Conditions: []servicecatalog.ServiceInstanceCondition{{Status: servicecatalog.ConditionTrue}}, + CurrentOperation: "", + Conditions: []servicecatalog.ServiceInstanceCondition{{Status: servicecatalog.ConditionTrue}}, }, valid: true, err: "", }, { - name: "Update instance condition to ready status and finish async op", + name: "Update instance condition to ready status and finish operation", old: &servicecatalog.ServiceInstanceStatus{ - AsyncOpInProgress: true, - Conditions: []servicecatalog.ServiceInstanceCondition{{Status: servicecatalog.ConditionFalse}}, + CurrentOperation: servicecatalog.ServiceInstanceOperationProvision, + OperationStartTime: &now, + InProgressProperties: &servicecatalog.ServiceInstancePropertiesState{}, + Conditions: []servicecatalog.ServiceInstanceCondition{{Status: servicecatalog.ConditionFalse}}, }, new: &servicecatalog.ServiceInstanceStatus{ - AsyncOpInProgress: false, - Conditions: []servicecatalog.ServiceInstanceCondition{{Status: servicecatalog.ConditionTrue}}, + CurrentOperation: "", + Conditions: []servicecatalog.ServiceInstanceCondition{{Status: servicecatalog.ConditionTrue}}, }, valid: true, err: "", @@ -315,8 +603,9 @@ func TestValidateServiceInstanceStatusUpdate(t *testing.T) { for _, tc := range cases { old := &servicecatalog.ServiceInstance{ ObjectMeta: metav1.ObjectMeta{ - Name: "test-instance", - Namespace: "test-ns", + Name: "test-instance", + Namespace: "test-ns", + Generation: 2, }, Spec: servicecatalog.ServiceInstanceSpec{ ServiceClassName: "test-serviceclass", @@ -324,10 +613,12 @@ func TestValidateServiceInstanceStatusUpdate(t *testing.T) { }, Status: *tc.old, } + old.Status.ReconciledGeneration = 1 new := &servicecatalog.ServiceInstance{ ObjectMeta: metav1.ObjectMeta{ - Name: "test-instance", - Namespace: "test-ns", + Name: "test-instance", + Namespace: "test-ns", + Generation: 2, }, Spec: servicecatalog.ServiceInstanceSpec{ ServiceClassName: "test-serviceclass", @@ -335,6 +626,7 @@ func TestValidateServiceInstanceStatusUpdate(t *testing.T) { }, Status: *tc.new, } + new.Status.ReconciledGeneration = 1 errs := ValidateServiceInstanceStatusUpdate(new, old) if len(errs) != 0 && tc.valid { @@ -346,7 +638,7 @@ func TestValidateServiceInstanceStatusUpdate(t *testing.T) { if !tc.valid { for _, err := range errs { if !strings.Contains(err.Detail, tc.err) { - t.Errorf("Error %q did not contain expected message %q", err.Detail, tc.err) + t.Errorf("%v: Error %q did not contain expected message %q", tc.name, err.Detail, tc.err) } } } diff --git a/pkg/apis/servicecatalog/validation/validation.go b/pkg/apis/servicecatalog/validation/validation.go new file mode 100644 index 00000000000..c4202462bba --- /dev/null +++ b/pkg/apis/servicecatalog/validation/validation.go @@ -0,0 +1,27 @@ +/* +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 validation + +import ( + "regexp" +) + +var hexademicalStringRegexp = regexp.MustCompile("^[[:xdigit:]]*$") + +func stringIsHexadecimal(s string) bool { + return hexademicalStringRegexp.MatchString(s) +} diff --git a/pkg/apis/servicecatalog/zz_generated.deepcopy.go b/pkg/apis/servicecatalog/zz_generated.deepcopy.go index d2120cc1556..8cb5068b1ef 100644 --- a/pkg/apis/servicecatalog/zz_generated.deepcopy.go +++ b/pkg/apis/servicecatalog/zz_generated.deepcopy.go @@ -54,9 +54,11 @@ func RegisterDeepCopies(scheme *runtime.Scheme) error { conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_servicecatalog_ServiceInstanceCredential, InType: reflect.TypeOf(&ServiceInstanceCredential{})}, conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_servicecatalog_ServiceInstanceCredentialCondition, InType: reflect.TypeOf(&ServiceInstanceCredentialCondition{})}, conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_servicecatalog_ServiceInstanceCredentialList, InType: reflect.TypeOf(&ServiceInstanceCredentialList{})}, + conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_servicecatalog_ServiceInstanceCredentialPropertiesState, InType: reflect.TypeOf(&ServiceInstanceCredentialPropertiesState{})}, conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_servicecatalog_ServiceInstanceCredentialSpec, InType: reflect.TypeOf(&ServiceInstanceCredentialSpec{})}, conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_servicecatalog_ServiceInstanceCredentialStatus, InType: reflect.TypeOf(&ServiceInstanceCredentialStatus{})}, conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_servicecatalog_ServiceInstanceList, InType: reflect.TypeOf(&ServiceInstanceList{})}, + conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_servicecatalog_ServiceInstancePropertiesState, InType: reflect.TypeOf(&ServiceInstancePropertiesState{})}, conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_servicecatalog_ServiceInstanceSpec, InType: reflect.TypeOf(&ServiceInstanceSpec{})}, conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_servicecatalog_ServiceInstanceStatus, InType: reflect.TypeOf(&ServiceInstanceStatus{})}, conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_servicecatalog_ServicePlan, InType: reflect.TypeOf(&ServicePlan{})}, @@ -400,6 +402,31 @@ func DeepCopy_servicecatalog_ServiceInstanceCredentialList(in interface{}, out i } } +// DeepCopy_servicecatalog_ServiceInstanceCredentialPropertiesState is an autogenerated deepcopy function. +func DeepCopy_servicecatalog_ServiceInstanceCredentialPropertiesState(in interface{}, out interface{}, c *conversion.Cloner) error { + { + in := in.(*ServiceInstanceCredentialPropertiesState) + out := out.(*ServiceInstanceCredentialPropertiesState) + *out = *in + if in.Parameters != nil { + in, out := &in.Parameters, &out.Parameters + if newVal, err := c.DeepCopy(*in); err != nil { + return err + } else { + *out = newVal.(*runtime.RawExtension) + } + } + if in.UserInfo != nil { + in, out := &in.UserInfo, &out.UserInfo + *out = new(UserInfo) + if err := DeepCopy_servicecatalog_UserInfo(*in, *out, c); err != nil { + return err + } + } + return nil + } +} + // DeepCopy_servicecatalog_ServiceInstanceCredentialSpec is an autogenerated deepcopy function. func DeepCopy_servicecatalog_ServiceInstanceCredentialSpec(in interface{}, out interface{}, c *conversion.Cloner) error { { @@ -454,6 +481,20 @@ func DeepCopy_servicecatalog_ServiceInstanceCredentialStatus(in interface{}, out *out = new(meta_v1.Time) **out = (*in).DeepCopy() } + if in.InProgressProperties != nil { + in, out := &in.InProgressProperties, &out.InProgressProperties + *out = new(ServiceInstanceCredentialPropertiesState) + if err := DeepCopy_servicecatalog_ServiceInstanceCredentialPropertiesState(*in, *out, c); err != nil { + return err + } + } + if in.ExternalProperties != nil { + in, out := &in.ExternalProperties, &out.ExternalProperties + *out = new(ServiceInstanceCredentialPropertiesState) + if err := DeepCopy_servicecatalog_ServiceInstanceCredentialPropertiesState(*in, *out, c); err != nil { + return err + } + } return nil } } @@ -477,6 +518,31 @@ func DeepCopy_servicecatalog_ServiceInstanceList(in interface{}, out interface{} } } +// DeepCopy_servicecatalog_ServiceInstancePropertiesState is an autogenerated deepcopy function. +func DeepCopy_servicecatalog_ServiceInstancePropertiesState(in interface{}, out interface{}, c *conversion.Cloner) error { + { + in := in.(*ServiceInstancePropertiesState) + out := out.(*ServiceInstancePropertiesState) + *out = *in + if in.Parameters != nil { + in, out := &in.Parameters, &out.Parameters + if newVal, err := c.DeepCopy(*in); err != nil { + return err + } else { + *out = newVal.(*runtime.RawExtension) + } + } + if in.UserInfo != nil { + in, out := &in.UserInfo, &out.UserInfo + *out = new(UserInfo) + if err := DeepCopy_servicecatalog_UserInfo(*in, *out, c); err != nil { + return err + } + } + return nil + } +} + // DeepCopy_servicecatalog_ServiceInstanceSpec is an autogenerated deepcopy function. func DeepCopy_servicecatalog_ServiceInstanceSpec(in interface{}, out interface{}, c *conversion.Cloner) error { { @@ -541,6 +607,20 @@ func DeepCopy_servicecatalog_ServiceInstanceStatus(in interface{}, out interface *out = new(meta_v1.Time) **out = (*in).DeepCopy() } + if in.InProgressProperties != nil { + in, out := &in.InProgressProperties, &out.InProgressProperties + *out = new(ServiceInstancePropertiesState) + if err := DeepCopy_servicecatalog_ServiceInstancePropertiesState(*in, *out, c); err != nil { + return err + } + } + if in.ExternalProperties != nil { + in, out := &in.ExternalProperties, &out.ExternalProperties + *out = new(ServiceInstancePropertiesState) + if err := DeepCopy_servicecatalog_ServiceInstancePropertiesState(*in, *out, c); err != nil { + return err + } + } return nil } } diff --git a/pkg/controller/controller_binding.go b/pkg/controller/controller_binding.go index 6f10fd54c02..db324ab089b 100644 --- a/pkg/controller/controller_binding.go +++ b/pkg/controller/controller_binding.go @@ -22,6 +22,7 @@ import ( "github.com/golang/glog" osb "github.com/pmorie/go-open-service-broker-client/v2" + "k8s.io/apimachinery/pkg/runtime" utilfeature "k8s.io/apiserver/pkg/util/feature" "github.com/kubernetes-incubator/service-catalog/pkg/apis/servicecatalog/v1alpha1" @@ -206,8 +207,9 @@ func (c *controller) reconcileServiceInstanceCredential(binding *v1alpha1.Servic glog.V(4).Infof("Adding/Updating ServiceInstanceCredential %v/%v", binding.Namespace, binding.Name) var parameters map[string]interface{} + var parametersWithSecretsRedacted map[string]interface{} if binding.Spec.Parameters != nil || binding.Spec.ParametersFrom != nil { - parameters, err = buildParameters(c.kubeClient, binding.Namespace, binding.Spec.ParametersFrom, binding.Spec.Parameters) + parameters, parametersWithSecretsRedacted, err = buildParameters(c.kubeClient, binding.Namespace, binding.Spec.ParametersFrom, binding.Spec.Parameters) if err != nil { s := fmt.Sprintf("Failed to prepare ServiceInstanceCredential parameters\n%s\n %s", binding.Spec.Parameters, err) glog.Warning(s) @@ -261,6 +263,56 @@ func (c *controller) reconcileServiceInstanceCredential(binding *v1alpha1.Servic return nil } + parametersChecksum := "" + if parameters != nil { + parametersChecksum, err = generateChecksumOfParameters(parameters) + if err != nil { + s := fmt.Sprintf(`Failed to generate the parameters checksum to store in the Status of ServiceInstanceCredential "%s/%s": %s`, binding.Namespace, binding.Name, err) + glog.Info(s) + c.recorder.Eventf(binding, api.EventTypeWarning, errorWithParameters, s) + c.setServiceInstanceCredentialCondition( + toUpdate, + v1alpha1.ServiceInstanceCredentialConditionReady, + v1alpha1.ConditionFalse, + errorWithParameters, + s) + if _, err := c.updateServiceInstanceCredentialStatus(toUpdate); err != nil { + return err + } + return err + } + } + + var rawParametersWithRedaction *runtime.RawExtension + if parametersWithSecretsRedacted != nil { + marshalledParametersWithRedaction, err := MarshalRawParameters(parametersWithSecretsRedacted) + if err != nil { + s := fmt.Sprintf(`Failed to marshal the parameters to store in the Status of ServiceInstanceCredential "%s/%s": %s`, binding.Namespace, binding.Name, err) + glog.Info(s) + c.recorder.Eventf(binding, api.EventTypeWarning, errorWithParameters, s) + c.setServiceInstanceCredentialCondition( + toUpdate, + v1alpha1.ServiceInstanceCredentialConditionReady, + v1alpha1.ConditionFalse, + errorWithParameters, + s) + if _, err := c.updateServiceInstanceCredentialStatus(toUpdate); err != nil { + return err + } + return err + } + + rawParametersWithRedaction = &runtime.RawExtension{ + Raw: marshalledParametersWithRedaction, + } + } + + toUpdate.Status.InProgressProperties = &v1alpha1.ServiceInstanceCredentialPropertiesState{ + Parameters: rawParametersWithRedaction, + ParametersChecksum: parametersChecksum, + UserInfo: toUpdate.Spec.UserInfo, + } + appGUID := string(ns.UID) request := &osb.BindRequest{ BindingID: binding.Spec.ExternalID, @@ -370,6 +422,8 @@ func (c *controller) reconcileServiceInstanceCredential(binding *v1alpha1.Servic return err } + toUpdate.Status.ExternalProperties = toUpdate.Status.InProgressProperties + err = c.injectServiceInstanceCredential(binding, response.Credentials) if err != nil { s := fmt.Sprintf("Error injecting binding results for ServiceInstanceCredential \"%s/%s\": %s", binding.Namespace, binding.Name, err) @@ -572,6 +626,9 @@ func (c *controller) reconcileServiceInstanceCredential(binding *v1alpha1.Servic "The binding was deleted successfully", ) c.clearServiceInstanceCredentialCurrentOperation(toUpdate) + + toUpdate.Status.ExternalProperties = nil + // Clear the finalizer finalizers.Delete(v1alpha1.FinalizerServiceCatalog) toUpdate.Finalizers = finalizers.List() @@ -830,4 +887,5 @@ func (c *controller) clearServiceInstanceCredentialCurrentOperation(toUpdate *v1 toUpdate.Status.CurrentOperation = "" toUpdate.Status.OperationStartTime = nil toUpdate.Status.ReconciledGeneration = toUpdate.Generation + toUpdate.Status.InProgressProperties = nil } diff --git a/pkg/controller/controller_binding_test.go b/pkg/controller/controller_binding_test.go index cb9aeacc831..c45147f4aef 100644 --- a/pkg/controller/controller_binding_test.go +++ b/pkg/controller/controller_binding_test.go @@ -31,6 +31,7 @@ import ( osb "github.com/pmorie/go-open-service-broker-client/v2" fakeosb "github.com/pmorie/go-open-service-broker-client/v2/fake" + apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/util/diff" @@ -75,7 +76,7 @@ func TestReconcileServiceInstanceCredentialNonExistingServiceInstance(t *testing t.Fatalf("Unexpected verb on actions[0]; expected %v, got %v", e, a) } updatedServiceInstanceCredential := assertUpdateStatus(t, actions[0], binding) - assertServiceInstanceCredentialErrorBeforeRequest(t, updatedServiceInstanceCredential, errorNonexistentServiceInstanceReason) + assertServiceInstanceCredentialErrorBeforeRequest(t, updatedServiceInstanceCredential, errorNonexistentServiceInstanceReason, binding) events := getRecordedEvents(testController) assertNumEvents(t, events, 1) @@ -129,7 +130,7 @@ func TestReconcileServiceInstanceCredentialNonExistingServiceClass(t *testing.T) // There should only be one action that says it failed because no such service class. updatedServiceInstanceCredential := assertUpdateStatus(t, actions[0], binding) - assertServiceInstanceCredentialErrorBeforeRequest(t, updatedServiceInstanceCredential, errorNonexistentServiceClassMessage) + assertServiceInstanceCredentialErrorBeforeRequest(t, updatedServiceInstanceCredential, errorNonexistentServiceClassMessage, binding) events := getRecordedEvents(testController) assertNumEvents(t, events, 1) @@ -200,10 +201,16 @@ func TestReconcileServiceInstanceCredentialWithSecretConflict(t *testing.T) { assertNumberOfActions(t, actions, 2) updatedServiceInstanceCredential := assertUpdateStatus(t, actions[0], binding).(*v1alpha1.ServiceInstanceCredential) - assertServiceInstanceCredentialOperationInProgress(t, updatedServiceInstanceCredential, v1alpha1.ServiceInstanceCredentialOperationBind) + assertServiceInstanceCredentialOperationInProgress(t, updatedServiceInstanceCredential, v1alpha1.ServiceInstanceCredentialOperationBind, binding) updatedServiceInstanceCredential = assertUpdateStatus(t, actions[1], binding).(*v1alpha1.ServiceInstanceCredential) - assertServiceInstanceCredentialRequestRetriableError(t, updatedServiceInstanceCredential, v1alpha1.ServiceInstanceCredentialOperationBind, errorInjectingBindResultReason) + assertServiceInstanceCredentialReadyFalse(t, updatedServiceInstanceCredential, errorInjectingBindResultReason) + assertServiceInstanceCredentialCurrentOperation(t, updatedServiceInstanceCredential, v1alpha1.ServiceInstanceCredentialOperationBind) + assertServiceInstanceCredentialOperationStartTimeSet(t, updatedServiceInstanceCredential, true) + assertServiceInstanceCredentialReconciledGeneration(t, updatedServiceInstanceCredential, binding.Status.ReconciledGeneration) + assertServiceInstanceCredentialInProgressPropertiesParameters(t, updatedServiceInstanceCredential, nil, "") + // External properties are updated because the bind request with the Broker was successful + assertServiceInstanceCredentialExternalPropertiesParameters(t, updatedServiceInstanceCredential, nil, "") kubeActions := fakeKubeClient.Actions() assertNumberOfActions(t, kubeActions, 2) @@ -296,14 +303,26 @@ func TestReconcileServiceInstanceCredentialWithParameters(t *testing.T) { }, }) + expectedParameters := map[string]interface{}{ + "args": []interface{}{ + "first-arg", + "second-arg", + }, + "name": "test-param", + } + expectedParametersChecksum, err := generateChecksumOfParameters(expectedParameters) + if err != nil { + t.Fatalf("Failed to generate parameters checksum: %v", err) + } + actions := fakeCatalogClient.Actions() assertNumberOfActions(t, actions, 2) updatedServiceInstanceCredential := assertUpdateStatus(t, actions[0], binding).(*v1alpha1.ServiceInstanceCredential) - assertServiceInstanceCredentialOperationInProgress(t, updatedServiceInstanceCredential, v1alpha1.ServiceInstanceCredentialOperationBind) + assertServiceInstanceCredentialOperationInProgressWithParameters(t, updatedServiceInstanceCredential, v1alpha1.ServiceInstanceCredentialOperationBind, expectedParameters, expectedParametersChecksum, binding) updatedServiceInstanceCredential = assertUpdateStatus(t, actions[1], binding).(*v1alpha1.ServiceInstanceCredential) - assertServiceInstanceCredentialOperationSuccess(t, updatedServiceInstanceCredential, v1alpha1.ServiceInstanceCredentialOperationBind) + assertServiceInstanceCredentialOperationSuccessWithParameters(t, updatedServiceInstanceCredential, v1alpha1.ServiceInstanceCredentialOperationBind, expectedParameters, expectedParametersChecksum, binding) kubeActions := fakeKubeClient.Actions() assertNumberOfActions(t, kubeActions, 3) @@ -391,7 +410,7 @@ func TestReconcileServiceInstanceCredentialNonbindableServiceClass(t *testing.T) // There should only be one action that says binding was created updatedServiceInstanceCredential := assertUpdateStatus(t, actions[0], binding) - assertServiceInstanceCredentialErrorBeforeRequest(t, updatedServiceInstanceCredential, errorNonbindableServiceClassReason) + assertServiceInstanceCredentialErrorBeforeRequest(t, updatedServiceInstanceCredential, errorNonbindableServiceClassReason, binding) events := getRecordedEvents(testController) assertNumEvents(t, events, 1) @@ -471,10 +490,10 @@ func TestReconcileServiceInstanceCredentialNonbindableServiceClassBindablePlan(t assertNumberOfActions(t, actions, 2) updatedServiceInstanceCredential := assertUpdateStatus(t, actions[0], binding) - assertServiceInstanceCredentialOperationInProgress(t, updatedServiceInstanceCredential, v1alpha1.ServiceInstanceCredentialOperationBind) + assertServiceInstanceCredentialOperationInProgress(t, updatedServiceInstanceCredential, v1alpha1.ServiceInstanceCredentialOperationBind, binding) updatedServiceInstanceCredential = assertUpdateStatus(t, actions[1], binding) - assertServiceInstanceCredentialOperationSuccess(t, updatedServiceInstanceCredential, v1alpha1.ServiceInstanceCredentialOperationBind) + assertServiceInstanceCredentialOperationSuccess(t, updatedServiceInstanceCredential, v1alpha1.ServiceInstanceCredentialOperationBind, binding) kubeActions := fakeKubeClient.Actions() assertNumberOfActions(t, kubeActions, 3) @@ -550,7 +569,7 @@ func TestReconcileServiceInstanceCredentialBindableServiceClassNonbindablePlan(t // There should only be one action that says binding was created updatedServiceInstanceCredential := assertUpdateStatus(t, actions[0], binding) - assertServiceInstanceCredentialErrorBeforeRequest(t, updatedServiceInstanceCredential, errorNonbindableServiceClassReason) + assertServiceInstanceCredentialErrorBeforeRequest(t, updatedServiceInstanceCredential, errorNonbindableServiceClassReason, binding) events := getRecordedEvents(testController) assertNumEvents(t, events, 1) @@ -606,7 +625,7 @@ func TestReconcileServiceInstanceCredentialFailsWithServiceInstanceAsyncOngoing( // There should only be one action that says binding was created updatedServiceInstanceCredential := assertUpdateStatus(t, actions[0], binding) - assertServiceInstanceCredentialErrorBeforeRequest(t, updatedServiceInstanceCredential, errorWithOngoingAsyncOperation) + assertServiceInstanceCredentialErrorBeforeRequest(t, updatedServiceInstanceCredential, errorWithOngoingAsyncOperation, binding) events := getRecordedEvents(testController) assertNumEvents(t, events, 1) @@ -659,7 +678,7 @@ func TestReconcileServiceInstanceCredentialServiceInstanceNotReady(t *testing.T) // There should only be one action that says binding was created updatedServiceInstanceCredential := assertUpdateStatus(t, actions[0], binding) - assertServiceInstanceCredentialErrorBeforeRequest(t, updatedServiceInstanceCredential, errorServiceInstanceNotReadyReason) + assertServiceInstanceCredentialErrorBeforeRequest(t, updatedServiceInstanceCredential, errorServiceInstanceNotReadyReason, binding) events := getRecordedEvents(testController) assertNumEvents(t, events, 1) @@ -708,7 +727,7 @@ func TestReconcileServiceInstanceCredentialNamespaceError(t *testing.T) { assertNumberOfActions(t, actions, 1) updatedServiceInstanceCredential := assertUpdateStatus(t, actions[0], binding) - assertServiceInstanceCredentialErrorBeforeRequest(t, updatedServiceInstanceCredential, errorFindingNamespaceServiceInstanceReason) + assertServiceInstanceCredentialErrorBeforeRequest(t, updatedServiceInstanceCredential, errorFindingNamespaceServiceInstanceReason, binding) events := getRecordedEvents(testController) assertNumEvents(t, events, 1) @@ -746,6 +765,7 @@ func TestReconcileServiceInstanceCredentialDelete(t *testing.T) { }, Status: v1alpha1.ServiceInstanceCredentialStatus{ ReconciledGeneration: 1, + ExternalProperties: &v1alpha1.ServiceInstanceCredentialPropertiesState{}, }, } @@ -787,10 +807,10 @@ func TestReconcileServiceInstanceCredentialDelete(t *testing.T) { assertNumberOfActions(t, actions, 2) updatedServiceInstanceCredential := assertUpdateStatus(t, actions[0], binding) - assertServiceInstanceCredentialOperationInProgress(t, updatedServiceInstanceCredential, v1alpha1.ServiceInstanceCredentialOperationUnbind) + assertServiceInstanceCredentialOperationInProgress(t, updatedServiceInstanceCredential, v1alpha1.ServiceInstanceCredentialOperationUnbind, binding) updatedServiceInstanceCredential = assertUpdateStatus(t, actions[1], binding) - assertServiceInstanceCredentialOperationSuccess(t, updatedServiceInstanceCredential, v1alpha1.ServiceInstanceCredentialOperationUnbind) + assertServiceInstanceCredentialOperationSuccess(t, updatedServiceInstanceCredential, v1alpha1.ServiceInstanceCredentialOperationUnbind, binding) events := getRecordedEvents(testController) assertNumEvents(t, events, 1) @@ -954,6 +974,7 @@ func TestReconcileServiceInstanceCredentialDeleteFailedServiceInstanceCredential binding := getTestServiceInstanceCredentialWithFailedStatus() binding.ObjectMeta.DeletionTimestamp = &metav1.Time{} binding.ObjectMeta.Finalizers = []string{v1alpha1.FinalizerServiceCatalog} + binding.Status.ExternalProperties = &v1alpha1.ServiceInstanceCredentialPropertiesState{} binding.ObjectMeta.Generation = 2 binding.Status.ReconciledGeneration = 1 @@ -996,10 +1017,10 @@ func TestReconcileServiceInstanceCredentialDeleteFailedServiceInstanceCredential assertNumberOfActions(t, actions, 2) updatedServiceInstanceCredential := assertUpdateStatus(t, actions[0], binding) - assertServiceInstanceCredentialOperationInProgress(t, updatedServiceInstanceCredential, v1alpha1.ServiceInstanceCredentialOperationUnbind) + assertServiceInstanceCredentialOperationInProgress(t, updatedServiceInstanceCredential, v1alpha1.ServiceInstanceCredentialOperationUnbind, binding) updatedServiceInstanceCredential = assertUpdateStatus(t, actions[1], binding) - assertServiceInstanceCredentialOperationSuccess(t, updatedServiceInstanceCredential, v1alpha1.ServiceInstanceCredentialOperationUnbind) + assertServiceInstanceCredentialOperationSuccess(t, updatedServiceInstanceCredential, v1alpha1.ServiceInstanceCredentialOperationUnbind, binding) events := getRecordedEvents(testController) assertNumEvents(t, events, 1) @@ -1052,10 +1073,10 @@ func TestReconcileServiceInstanceCredentialWithServiceBrokerError(t *testing.T) assertNumberOfActions(t, actions, 2) updatedServiceInstanceCredential := assertUpdateStatus(t, actions[0], binding) - assertServiceInstanceCredentialOperationInProgress(t, updatedServiceInstanceCredential, v1alpha1.ServiceInstanceCredentialOperationBind) + assertServiceInstanceCredentialOperationInProgress(t, updatedServiceInstanceCredential, v1alpha1.ServiceInstanceCredentialOperationBind, binding) updatedServiceInstanceCredential = assertUpdateStatus(t, actions[1], binding) - assertServiceInstanceCredentialRequestRetriableError(t, updatedServiceInstanceCredential, v1alpha1.ServiceInstanceCredentialOperationBind, errorBindCallReason) + assertServiceInstanceCredentialRequestRetriableError(t, updatedServiceInstanceCredential, v1alpha1.ServiceInstanceCredentialOperationBind, errorBindCallReason, binding) events := getRecordedEvents(testController) expectedEvent := api.EventTypeWarning + " " + errorBindCallReason + " " + `Error creating ServiceInstanceCredential "test-binding/test-ns" for ServiceInstance "test-ns/test-instance" of ServiceClass "test-serviceclass" at ServiceBroker "test-broker": Unexpected action` @@ -1109,10 +1130,10 @@ func TestReconcileServiceInstanceCredentialWithServiceBrokerHTTPError(t *testing assertNumberOfActions(t, actions, 2) updatedServiceInstanceCredential := assertUpdateStatus(t, actions[0], binding) - assertServiceInstanceCredentialOperationInProgress(t, updatedServiceInstanceCredential, v1alpha1.ServiceInstanceCredentialOperationBind) + assertServiceInstanceCredentialOperationInProgress(t, updatedServiceInstanceCredential, v1alpha1.ServiceInstanceCredentialOperationBind, binding) updatedServiceInstanceCredential = assertUpdateStatus(t, actions[1], binding) - assertServiceInstanceCredentialRequestFailingError(t, updatedServiceInstanceCredential, v1alpha1.ServiceInstanceCredentialOperationBind, errorBindCallReason, "ServiceInstanceCredentialReturnedFailure") + assertServiceInstanceCredentialRequestFailingError(t, updatedServiceInstanceCredential, v1alpha1.ServiceInstanceCredentialOperationBind, errorBindCallReason, "ServiceInstanceCredentialReturnedFailure", binding) events := getRecordedEvents(testController) expectedEvent := api.EventTypeWarning + " " + errorBindCallReason + " " + `Error creating ServiceInstanceCredential "test-binding/test-ns" for ServiceInstance "test-ns/test-instance" of ServiceClass "test-serviceclass" at ServiceBroker "test-broker", Status: 422; ErrorMessage: AsyncRequired; Description: This service plan requires client support for asynchronous service operations.; ResponseError: ` @@ -1185,10 +1206,10 @@ func TestReconcileServiceInstanceCredentialWithServiceInstanceCredentialCallFail assertNumberOfActions(t, actions, 2) updatedServiceInstanceCredential := assertUpdateStatus(t, actions[0], binding) - assertServiceInstanceCredentialOperationInProgress(t, updatedServiceInstanceCredential, v1alpha1.ServiceInstanceCredentialOperationBind) + assertServiceInstanceCredentialOperationInProgress(t, updatedServiceInstanceCredential, v1alpha1.ServiceInstanceCredentialOperationBind, binding) updatedServiceInstanceCredential = assertUpdateStatus(t, actions[1], binding) - assertServiceInstanceCredentialRequestRetriableError(t, updatedServiceInstanceCredential, v1alpha1.ServiceInstanceCredentialOperationBind, errorBindCallReason) + assertServiceInstanceCredentialRequestRetriableError(t, updatedServiceInstanceCredential, v1alpha1.ServiceInstanceCredentialOperationBind, errorBindCallReason, binding) brokerActions := fakeServiceBrokerClient.Actions() assertNumberOfServiceBrokerActions(t, brokerActions, 1) @@ -1249,10 +1270,10 @@ func TestReconcileServiceInstanceCredentialWithServiceInstanceCredentialFailure( assertNumberOfActions(t, actions, 2) updatedServiceInstanceCredential := assertUpdateStatus(t, actions[0], binding) - assertServiceInstanceCredentialOperationInProgress(t, updatedServiceInstanceCredential, v1alpha1.ServiceInstanceCredentialOperationBind) + assertServiceInstanceCredentialOperationInProgress(t, updatedServiceInstanceCredential, v1alpha1.ServiceInstanceCredentialOperationBind, binding) updatedServiceInstanceCredential = assertUpdateStatus(t, actions[1], binding) - assertServiceInstanceCredentialRequestFailingError(t, updatedServiceInstanceCredential, v1alpha1.ServiceInstanceCredentialOperationBind, errorBindCallReason, "ServiceInstanceCredentialReturnedFailure") + assertServiceInstanceCredentialRequestFailingError(t, updatedServiceInstanceCredential, v1alpha1.ServiceInstanceCredentialOperationBind, errorBindCallReason, "ServiceInstanceCredentialReturnedFailure", binding) brokerActions := fakeServiceBrokerClient.Actions() assertNumberOfServiceBrokerActions(t, brokerActions, 1) @@ -1458,6 +1479,9 @@ func TestReconcileUnbindingWithServiceBrokerError(t *testing.T) { ExternalID: bindingGUID, SecretName: testServiceInstanceCredentialSecretName, }, + Status: v1alpha1.ServiceInstanceCredentialStatus{ + ExternalProperties: &v1alpha1.ServiceInstanceCredentialPropertiesState{}, + }, } if err := scmeta.AddFinalizer(binding, v1alpha1.FinalizerServiceCatalog); err != nil { t.Fatalf("Finalizer error: %v", err) @@ -1470,10 +1494,10 @@ func TestReconcileUnbindingWithServiceBrokerError(t *testing.T) { assertNumberOfActions(t, actions, 2) updatedServiceInstanceCredential := assertUpdateStatus(t, actions[0], binding) - assertServiceInstanceCredentialOperationInProgress(t, updatedServiceInstanceCredential, v1alpha1.ServiceInstanceCredentialOperationUnbind) + assertServiceInstanceCredentialOperationInProgress(t, updatedServiceInstanceCredential, v1alpha1.ServiceInstanceCredentialOperationUnbind, binding) updatedServiceInstanceCredential = assertUpdateStatus(t, actions[1], binding) - assertServiceInstanceCredentialRequestRetriableError(t, updatedServiceInstanceCredential, v1alpha1.ServiceInstanceCredentialOperationUnbind, errorUnbindCallReason) + assertServiceInstanceCredentialRequestRetriableError(t, updatedServiceInstanceCredential, v1alpha1.ServiceInstanceCredentialOperationUnbind, errorUnbindCallReason, binding) events := getRecordedEvents(testController) expectedEvent := api.EventTypeWarning + " " + errorUnbindCallReason + " " + `Error unbinding ServiceInstanceCredential "test-binding/test-ns" for ServiceInstance "test-ns/test-instance" of ServiceClass "test-serviceclass" at ServiceBroker "test-broker": Unexpected action` @@ -1516,6 +1540,9 @@ func TestReconcileUnbindingWithServiceBrokerHTTPError(t *testing.T) { ExternalID: bindingGUID, SecretName: testServiceInstanceCredentialSecretName, }, + Status: v1alpha1.ServiceInstanceCredentialStatus{ + ExternalProperties: &v1alpha1.ServiceInstanceCredentialPropertiesState{}, + }, } if err := scmeta.AddFinalizer(binding, v1alpha1.FinalizerServiceCatalog); err != nil { t.Fatalf("Finalizer error: %v", err) @@ -1528,10 +1555,10 @@ func TestReconcileUnbindingWithServiceBrokerHTTPError(t *testing.T) { assertNumberOfActions(t, actions, 2) updatedServiceInstanceCredential := assertUpdateStatus(t, actions[0], binding) - assertServiceInstanceCredentialOperationInProgress(t, updatedServiceInstanceCredential, v1alpha1.ServiceInstanceCredentialOperationUnbind) + assertServiceInstanceCredentialOperationInProgress(t, updatedServiceInstanceCredential, v1alpha1.ServiceInstanceCredentialOperationUnbind, binding) updatedServiceInstanceCredential = assertUpdateStatus(t, actions[1], binding) - assertServiceInstanceCredentialRequestFailingError(t, updatedServiceInstanceCredential, v1alpha1.ServiceInstanceCredentialOperationUnbind, errorUnbindCallReason, errorUnbindCallReason) + assertServiceInstanceCredentialRequestFailingError(t, updatedServiceInstanceCredential, v1alpha1.ServiceInstanceCredentialOperationUnbind, errorUnbindCallReason, errorUnbindCallReason, binding) events := getRecordedEvents(testController) expectedEvent := api.EventTypeWarning + " " + errorUnbindCallReason + " " + `Error unbinding ServiceInstanceCredential "test-binding/test-ns" for ServiceInstance "test-ns/test-instance" of ServiceClass "test-serviceclass" at ServiceBroker "test-broker": Status: 410; ErrorMessage: ; Description: ; ResponseError: ` @@ -1690,7 +1717,7 @@ func TestReconcileBindingSuccessOnFinalRetry(t *testing.T) { assertNumberOfActions(t, actions, 1) updatedServiceInstanceCredential := assertUpdateStatus(t, actions[0], binding).(*v1alpha1.ServiceInstanceCredential) - assertServiceInstanceCredentialOperationSuccess(t, updatedServiceInstanceCredential, v1alpha1.ServiceInstanceCredentialOperationBind) + assertServiceInstanceCredentialOperationSuccess(t, updatedServiceInstanceCredential, v1alpha1.ServiceInstanceCredentialOperationBind, binding) events := getRecordedEvents(testController) assertNumEvents(t, events, 1) @@ -1734,7 +1761,7 @@ func TestReconcileBindingFailureOnFinalRetry(t *testing.T) { assertNumberOfActions(t, actions, 1) updatedServiceInstanceCredential := assertUpdateStatus(t, actions[0], binding).(*v1alpha1.ServiceInstanceCredential) - assertServiceInstanceCredentialRequestFailingError(t, updatedServiceInstanceCredential, v1alpha1.ServiceInstanceCredentialOperationBind, errorBindCallReason, errorReconciliationRetryTimeoutReason) + assertServiceInstanceCredentialRequestFailingError(t, updatedServiceInstanceCredential, v1alpha1.ServiceInstanceCredentialOperationBind, errorBindCallReason, errorReconciliationRetryTimeoutReason, binding) expectedEventPrefixes := []string{ api.EventTypeWarning + " " + errorBindCallReason, @@ -1816,7 +1843,14 @@ func TestReconcileBindingWithSecretConflictFailedAfterFinalRetry(t *testing.T) { assertNumberOfActions(t, actions, 1) updatedServiceInstanceCredential := assertUpdateStatus(t, actions[0], binding).(*v1alpha1.ServiceInstanceCredential) - assertServiceInstanceCredentialRequestFailingError(t, updatedServiceInstanceCredential, v1alpha1.ServiceInstanceCredentialOperationBind, errorInjectingBindResultReason, errorReconciliationRetryTimeoutReason) + assertServiceInstanceCredentialReadyFalse(t, updatedServiceInstanceCredential, errorInjectingBindResultReason) + assertServiceInstanceCredentialCondition(t, updatedServiceInstanceCredential, v1alpha1.ServiceInstanceCredentialConditionFailed, v1alpha1.ConditionTrue, errorReconciliationRetryTimeoutReason) + assertServiceInstanceCredentialCurrentOperationClear(t, updatedServiceInstanceCredential) + assertServiceInstanceCredentialOperationStartTimeSet(t, updatedServiceInstanceCredential, false) + assertServiceInstanceCredentialReconciledGeneration(t, updatedServiceInstanceCredential, binding.Generation) + assertServiceInstanceCredentialInProgressPropertiesNil(t, updatedServiceInstanceCredential) + // External properties are updated because the bind request with the Broker was successful + assertServiceInstanceCredentialExternalPropertiesParameters(t, updatedServiceInstanceCredential, nil, "") kubeActions := fakeKubeClient.Actions() assertNumberOfActions(t, kubeActions, 2) @@ -1844,7 +1878,7 @@ func TestReconcileBindingWithSecretConflictFailedAfterFinalRetry(t *testing.T) { } } -// TestReconcileServiceInstanceCrednetialWithStatusUpdateError verifies that the +// TestReconcileServiceInstanceCredentialWithStatusUpdateError verifies that the // reconciler returns an error when there is a conflict updating the status of // the resource. This is an otherwise successful scenario where the update to set // the in-progress operation fails. @@ -1880,8 +1914,141 @@ func TestReconcileServiceInstanceCredentialWithStatusUpdateError(t *testing.T) { assertNumberOfActions(t, actions, 1) updatedServiceInstanceCredential := assertUpdateStatus(t, actions[0], binding) - assertServiceInstanceCredentialOperationInProgress(t, updatedServiceInstanceCredential, v1alpha1.ServiceInstanceCredentialOperationBind) + assertServiceInstanceCredentialOperationInProgress(t, updatedServiceInstanceCredential, v1alpha1.ServiceInstanceCredentialOperationBind, binding) events := getRecordedEvents(testController) assertNumEvents(t, events, 0) } + +// TestReconcileServiceInstanceCredentailWithSecretParameters tests reconciling a +// binding that has parameters obtained from secrets. +func TestReconcileServiceInstanceCredentialWithSecretParameters(t *testing.T) { + fakeKubeClient, fakeCatalogClient, fakeServiceBrokerClient, testController, sharedInformers := newTestController(t, fakeosb.FakeClientConfiguration{ + BindReaction: &fakeosb.BindReaction{ + Response: &osb.BindResponse{ + Credentials: map[string]interface{}{ + "a": "b", + "c": "d", + }, + }, + }, + }) + + addGetNamespaceReaction(fakeKubeClient) + + paramSecret := &v1.Secret{ + Data: map[string][]byte{ + "param-secret-key": []byte("{\"b\":\"2\"}"), + }, + } + fakeKubeClient.AddReactor("get", "secrets", func(action clientgotesting.Action) (bool, runtime.Object, error) { + switch name := action.(clientgotesting.GetAction).GetName(); name { + case "param-secret-name": + return true, paramSecret, nil + default: + return true, nil, apierrors.NewNotFound(action.GetResource().GroupResource(), name) + } + }) + + sharedInformers.ServiceBrokers().Informer().GetStore().Add(getTestServiceBroker()) + sharedInformers.ServiceClasses().Informer().GetStore().Add(getTestServiceClass()) + sharedInformers.ServicePlans().Informer().GetStore().Add(getTestServicePlan()) + sharedInformers.ServiceInstances().Informer().GetStore().Add(getTestServiceInstanceWithStatus(v1alpha1.ConditionTrue)) + + binding := &v1alpha1.ServiceInstanceCredential{ + ObjectMeta: metav1.ObjectMeta{ + Name: testServiceInstanceCredentialName, + Namespace: testNamespace, + Generation: 1, + }, + Spec: v1alpha1.ServiceInstanceCredentialSpec{ + ServiceInstanceRef: v1.LocalObjectReference{Name: testServiceInstanceName}, + ExternalID: bindingGUID, + SecretName: testServiceInstanceCredentialSecretName, + }, + } + + parameters := map[string]interface{}{ + "a": "1", + } + b, err := json.Marshal(parameters) + if err != nil { + t.Fatalf("Failed to marshal parameters %v : %v", parameters, err) + } + binding.Spec.Parameters = &runtime.RawExtension{Raw: b} + + binding.Spec.ParametersFrom = []v1alpha1.ParametersFromSource{ + { + SecretKeyRef: &v1alpha1.SecretKeyReference{ + Name: "param-secret-name", + Key: "param-secret-key", + }, + }, + } + + err = testController.reconcileServiceInstanceCredential(binding) + if err != nil { + t.Fatalf("a valid binding should not fail: %v", err) + } + + brokerActions := fakeServiceBrokerClient.Actions() + assertNumberOfServiceBrokerActions(t, brokerActions, 1) + assertBind(t, brokerActions[0], &osb.BindRequest{ + BindingID: bindingGUID, + InstanceID: instanceGUID, + ServiceID: serviceClassGUID, + PlanID: planGUID, + AppGUID: strPtr(testNsUID), + Parameters: map[string]interface{}{ + "a": "1", + "b": "2", + }, + BindResource: &osb.BindResource{ + AppGUID: strPtr(testNsUID), + }, + }) + + expectedParameters := map[string]interface{}{ + "a": "1", + "b": "", + } + expectedParametersChecksum, err := generateChecksumOfParameters(map[string]interface{}{ + "a": "1", + "b": "2", + }) + if err != nil { + t.Fatalf("Failed to generate parameters checksum: %v", err) + } + + actions := fakeCatalogClient.Actions() + assertNumberOfActions(t, actions, 2) + + updatedServiceInstanceCredential := assertUpdateStatus(t, actions[0], binding) + assertServiceInstanceCredentialOperationInProgressWithParameters(t, updatedServiceInstanceCredential, v1alpha1.ServiceInstanceCredentialOperationBind, expectedParameters, expectedParametersChecksum, binding) + + updatedServiceInstanceCredential = assertUpdateStatus(t, actions[1], binding) + assertServiceInstanceCredentialOperationSuccessWithParameters(t, updatedServiceInstanceCredential, v1alpha1.ServiceInstanceCredentialOperationBind, expectedParameters, expectedParametersChecksum, binding) + + kubeActions := fakeKubeClient.Actions() + assertNumberOfActions(t, kubeActions, 4) + + // first action is a get on the secret, to build the parameters + action, ok := kubeActions[0].(clientgotesting.GetAction) + if !ok { + t.Fatalf("unexpected type of action: expected a GetAction, got %T", kubeActions[0]) + } + if e, a := "secrets", action.GetResource().Resource; e != a { + t.Fatalf("Unexpected resource on action: expected %q, got %q", e, a) + } + if e, a := "param-secret-name", action.GetName(); e != a { + t.Fatalf("Unexpected name of secret fetched: expected %q, got %q", e, a) + } + + events := getRecordedEvents(testController) + assertNumEvents(t, events, 1) + + expectedEvent := api.EventTypeNormal + " " + successInjectedBindResultReason + " " + successInjectedBindResultMessage + if e, a := expectedEvent, events[0]; e != a { + t.Fatalf("Received unexpected event: %v", a) + } +} diff --git a/pkg/controller/controller_instance.go b/pkg/controller/controller_instance.go index 7dffccab25d..4f6b2cc5090 100644 --- a/pkg/controller/controller_instance.go +++ b/pkg/controller/controller_instance.go @@ -22,6 +22,7 @@ import ( "github.com/golang/glog" osb "github.com/pmorie/go-open-service-broker-client/v2" + "k8s.io/apimachinery/pkg/runtime" utilfeature "k8s.io/apiserver/pkg/util/feature" "github.com/kubernetes-incubator/service-catalog/pkg/apis/servicecatalog/v1alpha1" @@ -416,6 +417,7 @@ func (c *controller) reconcileServiceInstanceDelete(instance *v1alpha1.ServiceIn glog.V(5).Infof("Deprovision call to broker succeeded for ServiceInstance %v/%v, finalizing", instance.Namespace, instance.Name) c.clearServiceInstanceCurrentOperation(toUpdate) + toUpdate.Status.ExternalProperties = nil setServiceInstanceCondition( toUpdate, @@ -525,8 +527,9 @@ func (c *controller) reconcileServiceInstance(instance *v1alpha1.ServiceInstance toUpdate := clone.(*v1alpha1.ServiceInstance) var parameters map[string]interface{} + var parametersWithSecretsRedacted map[string]interface{} if instance.Spec.Parameters != nil || instance.Spec.ParametersFrom != nil { - parameters, err = buildParameters(c.kubeClient, instance.Namespace, instance.Spec.ParametersFrom, instance.Spec.Parameters) + parameters, parametersWithSecretsRedacted, err = buildParameters(c.kubeClient, instance.Namespace, instance.Spec.ParametersFrom, instance.Spec.Parameters) if err != nil { s := fmt.Sprintf("Failed to prepare ServiceInstance parameters\n%s\n %s", instance.Spec.Parameters, err) glog.Warning(s) @@ -567,6 +570,57 @@ func (c *controller) reconcileServiceInstance(instance *v1alpha1.ServiceInstance return err } + parametersChecksum := "" + if parameters != nil { + parametersChecksum, err = generateChecksumOfParameters(parameters) + if err != nil { + s := fmt.Sprintf(`Failed to generate the parameters checksum to store in the Status of ServiceInstance "%s/%s": %s`, instance.Namespace, instance.Name, err) + glog.Info(s) + c.recorder.Eventf(instance, api.EventTypeWarning, errorWithParameters, s) + setServiceInstanceCondition( + toUpdate, + v1alpha1.ServiceInstanceConditionReady, + v1alpha1.ConditionFalse, + errorWithParameters, + s) + if _, err := c.updateServiceInstanceStatus(toUpdate); err != nil { + return err + } + return err + } + } + + var rawParametersWithRedaction *runtime.RawExtension + if parametersWithSecretsRedacted != nil { + marshalledParametersWithRedaction, err := MarshalRawParameters(parametersWithSecretsRedacted) + if err != nil { + s := fmt.Sprintf(`Failed to marshal the parameters to store in the Status of ServiceInstance "%s/%s": %s`, instance.Namespace, instance.Name, err) + glog.Info(s) + c.recorder.Eventf(instance, api.EventTypeWarning, errorWithParameters, s) + setServiceInstanceCondition( + toUpdate, + v1alpha1.ServiceInstanceConditionReady, + v1alpha1.ConditionFalse, + errorWithParameters, + s) + if _, err := c.updateServiceInstanceStatus(toUpdate); err != nil { + return err + } + return err + } + + rawParametersWithRedaction = &runtime.RawExtension{ + Raw: marshalledParametersWithRedaction, + } + } + + toUpdate.Status.InProgressProperties = &v1alpha1.ServiceInstancePropertiesState{ + PlanName: instance.Spec.PlanName, + Parameters: rawParametersWithRedaction, + ParametersChecksum: parametersChecksum, + UserInfo: instance.Spec.UserInfo, + } + request := &osb.ProvisionRequest{ AcceptsIncomplete: true, InstanceID: instance.Spec.ExternalID, @@ -723,6 +777,7 @@ func (c *controller) reconcileServiceInstance(instance *v1alpha1.ServiceInstance } else { glog.V(5).Infof("Successfully provisioned ServiceInstance %v/%v of ServiceClass %v at ServiceBroker %v: response: %+v", instance.Namespace, instance.Name, serviceClass.Name, brokerName, response) + toUpdate.Status.ExternalProperties = toUpdate.Status.InProgressProperties c.clearServiceInstanceCurrentOperation(toUpdate) // TODO: process response @@ -835,6 +890,7 @@ func (c *controller) pollServiceInstance(serviceClass *v1alpha1.ServiceClass, se toUpdate := clone.(*v1alpha1.ServiceInstance) c.clearServiceInstanceCurrentOperation(toUpdate) + toUpdate.Status.ExternalProperties = nil setServiceInstanceCondition( toUpdate, @@ -985,6 +1041,7 @@ func (c *controller) pollServiceInstance(serviceClass *v1alpha1.ServiceClass, se return err } toUpdate := clone.(*v1alpha1.ServiceInstance) + toUpdate.Status.ExternalProperties = toUpdate.Status.InProgressProperties c.clearServiceInstanceCurrentOperation(toUpdate) // If we were asynchronously deleting a Service Instance, finish @@ -1242,5 +1299,6 @@ func (c *controller) clearServiceInstanceCurrentOperation(toUpdate *v1alpha1.Ser toUpdate.Status.OperationStartTime = nil toUpdate.Status.AsyncOpInProgress = false toUpdate.Status.LastOperation = nil + toUpdate.Status.InProgressProperties = nil toUpdate.Status.ReconciledGeneration = toUpdate.Generation } diff --git a/pkg/controller/controller_instance_test.go b/pkg/controller/controller_instance_test.go index 00c1d961e1a..556f31370f0 100644 --- a/pkg/controller/controller_instance_test.go +++ b/pkg/controller/controller_instance_test.go @@ -75,7 +75,7 @@ func TestReconcileServiceInstanceNonExistentServiceClass(t *testing.T) { // There should only be one action that says it failed because no such class exists. updatedServiceInstance := assertUpdateStatus(t, actions[0], instance) - assertServiceInstanceErrorBeforeRequest(t, updatedServiceInstance, errorNonexistentServiceClassReason) + assertServiceInstanceErrorBeforeRequest(t, updatedServiceInstance, errorNonexistentServiceClassReason, instance) events := getRecordedEvents(testController) assertNumEvents(t, events, 1) @@ -108,7 +108,7 @@ func TestReconcileServiceInstanceNonExistentServiceBroker(t *testing.T) { // There should only be one action that says it failed because no such broker exists. updatedServiceInstance := assertUpdateStatus(t, actions[0], instance) - assertServiceInstanceErrorBeforeRequest(t, updatedServiceInstance, errorNonexistentServiceBrokerReason) + assertServiceInstanceErrorBeforeRequest(t, updatedServiceInstance, errorNonexistentServiceBrokerReason, instance) events := getRecordedEvents(testController) assertNumEvents(t, events, 1) @@ -157,7 +157,7 @@ func TestReconcileServiceInstanceWithAuthError(t *testing.T) { // There should only be one action that says it failed fetching auth credentials. updatedServiceInstance := assertUpdateStatus(t, actions[0], instance) - assertServiceInstanceErrorBeforeRequest(t, updatedServiceInstance, errorAuthCredentialsReason) + assertServiceInstanceErrorBeforeRequest(t, updatedServiceInstance, errorAuthCredentialsReason, instance) // verify one kube action occurred kubeActions := fakeKubeClient.Actions() @@ -210,7 +210,7 @@ func TestReconcileServiceInstanceNonExistentServicePlan(t *testing.T) { // There should only be one action that says it failed because no such broker exists. updatedServiceInstance := assertUpdateStatus(t, actions[0], instance) - assertServiceInstanceErrorBeforeRequest(t, updatedServiceInstance, errorNonexistentServicePlanReason) + assertServiceInstanceErrorBeforeRequest(t, updatedServiceInstance, errorNonexistentServicePlanReason, instance) // check to make sure the only event sent indicated that the instance references a non-existent // service plan @@ -269,14 +269,26 @@ func TestReconcileServiceInstanceWithParameters(t *testing.T) { }, }) + expectedParameters := map[string]interface{}{ + "args": map[string]interface{}{ + "first": "first-arg", + "second": "second-arg", + }, + "name": "test-param", + } + expectedParametersChecksum, err := generateChecksumOfParameters(expectedParameters) + if err != nil { + t.Fatalf("Failed to generate parameters checksum: %v", err) + } + actions := fakeCatalogClient.Actions() assertNumberOfActions(t, actions, 2) updatedServiceInstance := assertUpdateStatus(t, actions[0], instance) - assertServiceInstanceOperationInProgress(t, updatedServiceInstance, v1alpha1.ServiceInstanceOperationProvision) + assertServiceInstanceOperationInProgressWithParameters(t, updatedServiceInstance, v1alpha1.ServiceInstanceOperationProvision, expectedParameters, expectedParametersChecksum, instance) updatedServiceInstance = assertUpdateStatus(t, actions[1], instance) - assertServiceInstanceOperationSuccess(t, updatedServiceInstance, v1alpha1.ServiceInstanceOperationProvision) + assertServiceInstanceOperationSuccessWithParameters(t, updatedServiceInstance, v1alpha1.ServiceInstanceOperationProvision, expectedParameters, expectedParametersChecksum, instance) updateObject, ok := updatedServiceInstance.(*v1alpha1.ServiceInstance) if !ok { @@ -340,7 +352,7 @@ func TestReconcileServiceInstanceWithInvalidParameters(t *testing.T) { // There should only be one action that says that the parameters were invalid. updatedServiceInstance := assertUpdateStatus(t, actions[0], instance) - assertServiceInstanceErrorBeforeRequest(t, updatedServiceInstance, errorWithParameters) + assertServiceInstanceErrorBeforeRequest(t, updatedServiceInstance, errorWithParameters, instance) // verify no kube resources created kubeActions := fakeKubeClient.Actions() @@ -401,10 +413,10 @@ func TestReconcileServiceInstanceWithProvisionCallFailure(t *testing.T) { assertNumberOfActions(t, actions, 2) updatedServiceInstance := assertUpdateStatus(t, actions[0], instance) - assertServiceInstanceOperationInProgress(t, updatedServiceInstance, v1alpha1.ServiceInstanceOperationProvision) + assertServiceInstanceOperationInProgress(t, updatedServiceInstance, v1alpha1.ServiceInstanceOperationProvision, instance) updatedServiceInstance = assertUpdateStatus(t, actions[1], instance) - assertServiceInstanceRequestRetriableError(t, updatedServiceInstance, v1alpha1.ServiceInstanceOperationProvision, errorErrorCallingProvisionReason) + assertServiceInstanceRequestRetriableError(t, updatedServiceInstance, v1alpha1.ServiceInstanceOperationProvision, errorErrorCallingProvisionReason, instance) events := getRecordedEvents(testController) assertNumEvents(t, events, 1) @@ -464,10 +476,10 @@ func TestReconcileServiceInstanceWithProvisionFailure(t *testing.T) { assertNumberOfActions(t, actions, 2) updatedServiceInstance := assertUpdateStatus(t, actions[0], instance) - assertServiceInstanceOperationInProgress(t, updatedServiceInstance, v1alpha1.ServiceInstanceOperationProvision) + assertServiceInstanceOperationInProgress(t, updatedServiceInstance, v1alpha1.ServiceInstanceOperationProvision, instance) updatedServiceInstance = assertUpdateStatus(t, actions[1], instance) - assertServiceInstanceRequestFailingError(t, updatedServiceInstance, v1alpha1.ServiceInstanceOperationProvision, errorProvisionCallFailedReason, "ServiceBrokerReturnedFailure") + assertServiceInstanceRequestFailingError(t, updatedServiceInstance, v1alpha1.ServiceInstanceOperationProvision, errorProvisionCallFailedReason, "ServiceBrokerReturnedFailure", instance) events := getRecordedEvents(testController) assertNumEvents(t, events, 1) @@ -535,10 +547,10 @@ func TestReconcileServiceInstance(t *testing.T) { } updatedServiceInstance := assertUpdateStatus(t, actions[0], instance) - assertServiceInstanceOperationInProgress(t, updatedServiceInstance, v1alpha1.ServiceInstanceOperationProvision) + assertServiceInstanceOperationInProgress(t, updatedServiceInstance, v1alpha1.ServiceInstanceOperationProvision, instance) updatedServiceInstance = assertUpdateStatus(t, actions[1], instance) - assertServiceInstanceOperationSuccess(t, updatedServiceInstance, v1alpha1.ServiceInstanceOperationProvision) + assertServiceInstanceOperationSuccess(t, updatedServiceInstance, v1alpha1.ServiceInstanceOperationProvision, instance) assertServiceInstanceDashboardURL(t, updatedServiceInstance, testDashboardURL) events := getRecordedEvents(testController) @@ -601,10 +613,10 @@ func TestReconcileServiceInstanceAsynchronous(t *testing.T) { assertNumberOfActions(t, actions, 2) updatedServiceInstance := assertUpdateStatus(t, actions[0], instance) - assertServiceInstanceOperationInProgress(t, updatedServiceInstance, v1alpha1.ServiceInstanceOperationProvision) + assertServiceInstanceOperationInProgress(t, updatedServiceInstance, v1alpha1.ServiceInstanceOperationProvision, instance) updatedServiceInstance = assertUpdateStatus(t, actions[1], instance) - assertServiceInstanceAsyncInProgress(t, updatedServiceInstance, v1alpha1.ServiceInstanceOperationProvision, testOperation) + assertServiceInstanceAsyncInProgress(t, updatedServiceInstance, v1alpha1.ServiceInstanceOperationProvision, testOperation, instance) assertServiceInstanceDashboardURL(t, updatedServiceInstance, testDashboardURL) // verify no kube resources created. @@ -668,10 +680,10 @@ func TestReconcileServiceInstanceAsynchronousNoOperation(t *testing.T) { assertNumberOfActions(t, actions, 2) updatedServiceInstance := assertUpdateStatus(t, actions[0], instance) - assertServiceInstanceOperationInProgress(t, updatedServiceInstance, v1alpha1.ServiceInstanceOperationProvision) + assertServiceInstanceOperationInProgress(t, updatedServiceInstance, v1alpha1.ServiceInstanceOperationProvision, instance) updatedServiceInstance = assertUpdateStatus(t, actions[1], instance) - assertServiceInstanceAsyncInProgress(t, updatedServiceInstance, v1alpha1.ServiceInstanceOperationProvision, "") + assertServiceInstanceAsyncInProgress(t, updatedServiceInstance, v1alpha1.ServiceInstanceOperationProvision, "", instance) assertServiceInstanceDashboardURL(t, updatedServiceInstance, testDashboardURL) // verify no kube resources created. @@ -721,7 +733,7 @@ func TestReconcileServiceInstanceNamespaceError(t *testing.T) { assertNumberOfActions(t, actions, 1) updatedServiceInstance := assertUpdateStatus(t, actions[0], instance) - assertServiceInstanceErrorBeforeRequest(t, updatedServiceInstance, errorFindingNamespaceServiceInstanceReason) + assertServiceInstanceErrorBeforeRequest(t, updatedServiceInstance, errorFindingNamespaceServiceInstanceReason, instance) events := getRecordedEvents(testController) assertNumEvents(t, events, 1) @@ -751,6 +763,7 @@ func TestReconcileServiceInstanceDelete(t *testing.T) { // as that implies a previous success. instance.Generation = 2 instance.Status.ReconciledGeneration = 1 + instance.Status.ExternalProperties = &v1alpha1.ServiceInstancePropertiesState{} fakeCatalogClient.AddReactor("get", "serviceinstances", func(action clientgotesting.Action) (bool, runtime.Object, error) { return true, instance, nil @@ -778,10 +791,10 @@ func TestReconcileServiceInstanceDelete(t *testing.T) { assertNumberOfActions(t, actions, 2) updatedServiceInstance := assertUpdateStatus(t, actions[0], instance) - assertServiceInstanceOperationInProgress(t, updatedServiceInstance, v1alpha1.ServiceInstanceOperationDeprovision) + assertServiceInstanceOperationInProgress(t, updatedServiceInstance, v1alpha1.ServiceInstanceOperationDeprovision, instance) updatedServiceInstance = assertUpdateStatus(t, actions[1], instance) - assertServiceInstanceOperationSuccess(t, updatedServiceInstance, v1alpha1.ServiceInstanceOperationDeprovision) + assertServiceInstanceOperationSuccess(t, updatedServiceInstance, v1alpha1.ServiceInstanceOperationDeprovision, instance) events := getRecordedEvents(testController) assertNumEvents(t, events, 1) @@ -816,6 +829,7 @@ func TestReconcileServiceInstanceDeleteBlockedByCredentials(t *testing.T) { // as that implies a previous success. instance.Generation = 2 instance.Status.ReconciledGeneration = 1 + instance.Status.ExternalProperties = &v1alpha1.ServiceInstancePropertiesState{} fakeCatalogClient.AddReactor("get", "serviceinstances", func(action clientgotesting.Action) (bool, runtime.Object, error) { return true, instance, nil @@ -837,7 +851,7 @@ func TestReconcileServiceInstanceDeleteBlockedByCredentials(t *testing.T) { assertNumberOfActions(t, actions, 1) updatedServiceInstance := assertUpdateStatus(t, actions[0], instance) - assertServiceInstanceErrorBeforeRequest(t, updatedServiceInstance, "DeprovisionBlockedByExistingCredentials") + assertServiceInstanceErrorBeforeRequest(t, updatedServiceInstance, "DeprovisionBlockedByExistingCredentials", instance) events := getRecordedEvents(testController) assertNumEvents(t, events, 1) @@ -882,10 +896,10 @@ func TestReconcileServiceInstanceDeleteBlockedByCredentials(t *testing.T) { assertNumberOfActions(t, actions, 2) updatedServiceInstance = assertUpdateStatus(t, actions[0], instance) - assertServiceInstanceOperationInProgress(t, updatedServiceInstance, v1alpha1.ServiceInstanceOperationDeprovision) + assertServiceInstanceOperationInProgress(t, updatedServiceInstance, v1alpha1.ServiceInstanceOperationDeprovision, instance) updatedServiceInstance = assertUpdateStatus(t, actions[1], instance) - assertServiceInstanceOperationSuccess(t, updatedServiceInstance, v1alpha1.ServiceInstanceOperationDeprovision) + assertServiceInstanceOperationSuccess(t, updatedServiceInstance, v1alpha1.ServiceInstanceOperationDeprovision, instance) events = getRecordedEvents(testController) assertNumEvents(t, events, 1) @@ -917,6 +931,7 @@ func TestReconcileServiceInstanceDeleteAsynchronous(t *testing.T) { // as that implies a previous success. instance.Generation = 2 instance.Status.ReconciledGeneration = 1 + instance.Status.ExternalProperties = &v1alpha1.ServiceInstancePropertiesState{} fakeCatalogClient.AddReactor("get", "serviceinstances", func(action clientgotesting.Action) (bool, runtime.Object, error) { return true, instance, nil @@ -956,10 +971,10 @@ func TestReconcileServiceInstanceDeleteAsynchronous(t *testing.T) { assertNumberOfActions(t, actions, 2) updatedServiceInstance := assertUpdateStatus(t, actions[0], instance) - assertServiceInstanceOperationInProgress(t, updatedServiceInstance, v1alpha1.ServiceInstanceOperationDeprovision) + assertServiceInstanceOperationInProgress(t, updatedServiceInstance, v1alpha1.ServiceInstanceOperationDeprovision, instance) updatedServiceInstance = assertUpdateStatus(t, actions[1], instance) - assertServiceInstanceAsyncInProgress(t, updatedServiceInstance, v1alpha1.ServiceInstanceOperationDeprovision, testOperation) + assertServiceInstanceAsyncInProgress(t, updatedServiceInstance, v1alpha1.ServiceInstanceOperationDeprovision, testOperation, instance) events := getRecordedEvents(testController) assertNumEvents(t, events, 1) @@ -982,6 +997,7 @@ func TestReconcileServiceInstanceDeleteFailedInstance(t *testing.T) { instance := getTestServiceInstanceWithFailedStatus() instance.ObjectMeta.DeletionTimestamp = &metav1.Time{} instance.ObjectMeta.Finalizers = []string{v1alpha1.FinalizerServiceCatalog} + instance.Status.ExternalProperties = &v1alpha1.ServiceInstancePropertiesState{} // we only invoke the broker client to deprovision if we have a reconciled generation set // as that implies a previous success. @@ -1053,8 +1069,6 @@ func TestReconcileServiceInstanceDeleteDoesNotInvokeServiceBroker(t *testing.T) updatedServiceInstance := assertUpdateStatus(t, actions[0], instance) assertEmptyFinalizers(t, updatedServiceInstance) - assertServiceInstanceCurrentOperationClear(t, updatedServiceInstance) - assertServiceInstanceOperationStartTimeSet(t, updatedServiceInstance, false) // no events because no external deprovision was needed events := getRecordedEvents(testController) @@ -1144,7 +1158,7 @@ func TestPollServiceInstanceInProgressProvisioningWithOperation(t *testing.T) { assertNumberOfActions(t, actions, 1) updatedServiceInstance := assertUpdateStatus(t, actions[0], instance) - assertServiceInstanceAsyncInProgress(t, updatedServiceInstance, v1alpha1.ServiceInstanceOperationProvision, testOperation) + assertServiceInstanceAsyncInProgress(t, updatedServiceInstance, v1alpha1.ServiceInstanceOperationProvision, testOperation, instance) assertServiceInstanceConditionHasLastOperationDescription(t, updatedServiceInstance, v1alpha1.ServiceInstanceOperationProvision, lastOperationDescription) // verify no kube resources created. @@ -1205,7 +1219,7 @@ func TestPollServiceInstanceSuccessProvisioningWithOperation(t *testing.T) { assertNumberOfActions(t, actions, 1) updatedServiceInstance := assertUpdateStatus(t, actions[0], instance) - assertServiceInstanceOperationSuccess(t, updatedServiceInstance, v1alpha1.ServiceInstanceOperationProvision) + assertServiceInstanceOperationSuccess(t, updatedServiceInstance, v1alpha1.ServiceInstanceOperationProvision, instance) } // TestPollServiceInstanceFailureProvisioningWithOperation tests polling an @@ -1259,7 +1273,7 @@ func TestPollServiceInstanceFailureProvisioningWithOperation(t *testing.T) { assertNumberOfActions(t, actions, 1) updatedServiceInstance := assertUpdateStatus(t, actions[0], instance) - assertServiceInstanceRequestFailingError(t, updatedServiceInstance, v1alpha1.ServiceInstanceOperationProvision, errorProvisionCallFailedReason, errorProvisionCallFailedReason) + assertServiceInstanceRequestFailingError(t, updatedServiceInstance, v1alpha1.ServiceInstanceOperationProvision, errorProvisionCallFailedReason, errorProvisionCallFailedReason, instance) } // TestPollServiceInstanceInProgressDeprovisioningWithOperationNoFinalizer tests @@ -1311,7 +1325,7 @@ func TestPollServiceInstanceInProgressDeprovisioningWithOperationNoFinalizer(t * assertNumberOfActions(t, actions, 1) updatedServiceInstance := assertUpdateStatus(t, actions[0], instance) - assertServiceInstanceAsyncInProgress(t, updatedServiceInstance, v1alpha1.ServiceInstanceOperationDeprovision, testOperation) + assertServiceInstanceAsyncInProgress(t, updatedServiceInstance, v1alpha1.ServiceInstanceOperationDeprovision, testOperation, instance) assertServiceInstanceConditionHasLastOperationDescription(t, updatedServiceInstance, v1alpha1.ServiceInstanceOperationDeprovision, lastOperationDescription) // verify no kube resources created. @@ -1371,7 +1385,7 @@ func TestPollServiceInstanceSuccessDeprovisioningWithOperationNoFinalizer(t *tes assertNumberOfActions(t, actions, 1) updatedServiceInstance := assertUpdateStatus(t, actions[0], instance) - assertServiceInstanceOperationSuccess(t, updatedServiceInstance, v1alpha1.ServiceInstanceOperationDeprovision) + assertServiceInstanceOperationSuccess(t, updatedServiceInstance, v1alpha1.ServiceInstanceOperationDeprovision, instance) events := getRecordedEvents(testController) assertNumEvents(t, events, 1) @@ -1432,7 +1446,7 @@ func TestPollServiceInstanceFailureDeprovisioningWithOperation(t *testing.T) { assertNumberOfActions(t, actions, 1) updatedServiceInstance := assertUpdateStatus(t, actions[0], instance) - assertServiceInstanceRequestFailingError(t, updatedServiceInstance, v1alpha1.ServiceInstanceOperationDeprovision, errorDeprovisionCalledReason, errorDeprovisionCalledReason) + assertServiceInstanceRequestFailingError(t, updatedServiceInstance, v1alpha1.ServiceInstanceOperationDeprovision, errorDeprovisionCalledReason, errorDeprovisionCalledReason, instance) events := getRecordedEvents(testController) assertNumEvents(t, events, 1) @@ -1494,7 +1508,7 @@ func TestPollServiceInstanceStatusGoneDeprovisioningWithOperationNoFinalizer(t * assertNumberOfActions(t, actions, 1) updatedServiceInstance := assertUpdateStatus(t, actions[0], instance) - assertServiceInstanceOperationSuccess(t, updatedServiceInstance, v1alpha1.ServiceInstanceOperationDeprovision) + assertServiceInstanceOperationSuccess(t, updatedServiceInstance, v1alpha1.ServiceInstanceOperationDeprovision, instance) events := getRecordedEvents(testController) assertNumEvents(t, events, 1) @@ -1618,7 +1632,7 @@ func TestPollServiceInstanceSuccessDeprovisioningWithOperationWithFinalizer(t *t assertNumberOfActions(t, actions, 1) updatedServiceInstance := assertUpdateStatus(t, actions[0], instance) - assertServiceInstanceOperationSuccess(t, updatedServiceInstance, v1alpha1.ServiceInstanceOperationDeprovision) + assertServiceInstanceOperationSuccess(t, updatedServiceInstance, v1alpha1.ServiceInstanceOperationDeprovision, instance) events := getRecordedEvents(testController) assertNumEvents(t, events, 1) @@ -1667,7 +1681,7 @@ func TestReconcileServiceInstanceSuccessOnFinalRetry(t *testing.T) { assertNumberOfActions(t, actions, 1) updatedServiceInstance := assertUpdateStatus(t, actions[0], instance) - assertServiceInstanceOperationSuccess(t, updatedServiceInstance, v1alpha1.ServiceInstanceOperationProvision) + assertServiceInstanceOperationSuccess(t, updatedServiceInstance, v1alpha1.ServiceInstanceOperationProvision, instance) // verify no kube resources created // One single action comes from getting namespace uid @@ -1735,7 +1749,7 @@ func TestReconcileServiceInstanceFailureOnFinalRetry(t *testing.T) { assertNumberOfActions(t, actions, 1) updatedServiceInstance := assertUpdateStatus(t, actions[0], instance) - assertServiceInstanceRequestFailingError(t, updatedServiceInstance, v1alpha1.ServiceInstanceOperationProvision, errorErrorCallingProvisionReason, errorReconciliationRetryTimeoutReason) + assertServiceInstanceRequestFailingError(t, updatedServiceInstance, v1alpha1.ServiceInstanceOperationProvision, errorErrorCallingProvisionReason, errorReconciliationRetryTimeoutReason, instance) expectedEventPrefixes := []string{ api.EventTypeWarning + " " + errorErrorCallingProvisionReason, @@ -1804,7 +1818,7 @@ func TestPollServiceInstanceSuccessOnFinalRetry(t *testing.T) { assertNumberOfActions(t, actions, 1) updatedServiceInstance := assertUpdateStatus(t, actions[0], instance) - assertServiceInstanceOperationSuccess(t, updatedServiceInstance, v1alpha1.ServiceInstanceOperationProvision) + assertServiceInstanceOperationSuccess(t, updatedServiceInstance, v1alpha1.ServiceInstanceOperationProvision, instance) } // TestPollServiceInstanceFailureOnFinalRetry verifies that polling @@ -1854,7 +1868,7 @@ func TestPollServiceInstanceFailureOnFinalRetry(t *testing.T) { assertNumberOfActions(t, actions, 1) updatedServiceInstance := assertUpdateStatus(t, actions[0], instance) - assertServiceInstanceRequestFailingError(t, updatedServiceInstance, v1alpha1.ServiceInstanceOperationProvision, asyncProvisioningReason, errorReconciliationRetryTimeoutReason) + assertServiceInstanceRequestFailingError(t, updatedServiceInstance, v1alpha1.ServiceInstanceOperationProvision, asyncProvisioningReason, errorReconciliationRetryTimeoutReason, instance) assertServiceInstanceConditionHasLastOperationDescription(t, updatedServiceInstance, v1alpha1.ServiceInstanceOperationProvision, lastOperationDescription) // verify no kube resources created. @@ -1897,7 +1911,7 @@ func TestReconcileServiceInstanceWithStatusUpdateError(t *testing.T) { assertNumberOfActions(t, actions, 1) updatedServiceInstance := assertUpdateStatus(t, actions[0], instance) - assertServiceInstanceOperationInProgress(t, updatedServiceInstance, v1alpha1.ServiceInstanceOperationProvision) + assertServiceInstanceOperationInProgress(t, updatedServiceInstance, v1alpha1.ServiceInstanceOperationProvision, instance) events := getRecordedEvents(testController) assertNumEvents(t, events, 0) @@ -2370,3 +2384,115 @@ func TestPollInstanceUsingOriginatingIdentity(t *testing.T) { }() } } + +// TestReconcileServiceInstanceWithSecretParameters tests reconciling an instance +// that has parameters obtained from secrets. +func TestReconcileServiceInstanceWithSecretParameters(t *testing.T) { + fakeKubeClient, fakeCatalogClient, fakeServiceBrokerClient, testController, sharedInformers := newTestController(t, fakeosb.FakeClientConfiguration{ + ProvisionReaction: &fakeosb.ProvisionReaction{ + Response: &osb.ProvisionResponse{}, + }, + }) + + paramSecret := &v1.Secret{ + Data: map[string][]byte{ + "param-secret-key": []byte("{\"b\":\"2\"}"), + }, + } + addGetSecretReaction(fakeKubeClient, paramSecret) + + sharedInformers.ServiceBrokers().Informer().GetStore().Add(getTestServiceBroker()) + sharedInformers.ServiceClasses().Informer().GetStore().Add(getTestServiceClass()) + sharedInformers.ServicePlans().Informer().GetStore().Add(getTestServicePlan()) + + instance := getTestServiceInstance() + + parameters := map[string]interface{}{ + "a": "1", + } + b, err := json.Marshal(parameters) + if err != nil { + t.Fatalf("Failed to marshal parameters %v : %v", parameters, err) + } + instance.Spec.Parameters = &runtime.RawExtension{Raw: b} + + instance.Spec.ParametersFrom = []v1alpha1.ParametersFromSource{ + { + SecretKeyRef: &v1alpha1.SecretKeyReference{ + Name: "param-secret-name", + Key: "param-secret-key", + }, + }, + } + + if err = testController.reconcileServiceInstance(instance); err != nil { + t.Fatalf("This should not fail : %v", err) + } + + brokerActions := fakeServiceBrokerClient.Actions() + assertNumberOfServiceBrokerActions(t, brokerActions, 1) + assertProvision(t, brokerActions[0], &osb.ProvisionRequest{ + AcceptsIncomplete: true, + InstanceID: instanceGUID, + ServiceID: serviceClassGUID, + PlanID: planGUID, + Context: map[string]interface{}{ + "platform": "kubernetes", + "namespace": "test-ns", + }, + Parameters: map[string]interface{}{ + "a": "1", + "b": "2", + }, + }) + + expectedParameters := map[string]interface{}{ + "a": "1", + "b": "", + } + expectedParametersChecksum, err := generateChecksumOfParameters(map[string]interface{}{ + "a": "1", + "b": "2", + }) + if err != nil { + t.Fatalf("Failed to generate parameters checksum: %v", err) + } + + actions := fakeCatalogClient.Actions() + assertNumberOfActions(t, actions, 2) + + updatedServiceInstance := assertUpdateStatus(t, actions[0], instance) + assertServiceInstanceOperationInProgressWithParameters(t, updatedServiceInstance, v1alpha1.ServiceInstanceOperationProvision, expectedParameters, expectedParametersChecksum, instance) + + updatedServiceInstance = assertUpdateStatus(t, actions[1], instance) + assertServiceInstanceOperationSuccessWithParameters(t, updatedServiceInstance, v1alpha1.ServiceInstanceOperationProvision, expectedParameters, expectedParametersChecksum, instance) + + updateObject, ok := updatedServiceInstance.(*v1alpha1.ServiceInstance) + if !ok { + t.Fatalf("couldn't convert to *v1alpha1.ServiceInstance") + } + + // Verify parameters are what we'd expect them to be, basically name, map with two values in it. + if len(updateObject.Spec.Parameters.Raw) == 0 { + t.Fatalf("Parameters was unexpectedly empty") + } + + // verify no kube resources created + // First action is getting the parameter secret + // Second action is getting the namespace uid + kubeActions := fakeKubeClient.Actions() + if err := checkKubeClientActions(kubeActions, []kubeClientAction{ + {verb: "get", resourceName: "secrets", checkType: checkGetActionType}, + {verb: "get", resourceName: "namespaces", checkType: checkGetActionType}, + }); err != nil { + t.Fatal(err) + } + + events := getRecordedEvents(testController) + assertNumEvents(t, events, 1) + + expectedEvent := api.EventTypeNormal + " " + successProvisionReason + " " + "The instance was provisioned successfully" + if e, a := expectedEvent, events[0]; e != a { + t.Fatalf("Received unexpected event: %v", a) + } +} diff --git a/pkg/controller/controller_test.go b/pkg/controller/controller_test.go index 0988a525a29..e1c75a04426 100644 --- a/pkg/controller/controller_test.go +++ b/pkg/controller/controller_test.go @@ -24,6 +24,7 @@ import ( "testing" "time" + "github.com/ghodss/yaml" osb "github.com/pmorie/go-open-service-broker-client/v2" fakeosb "github.com/pmorie/go-open-service-broker-client/v2/fake" @@ -520,9 +521,10 @@ func getTestServiceInstanceAsyncProvisioning(operation string) *v1alpha1.Service Message: "Provisioning", LastTransitionTime: metav1.NewTime(time.Now().Add(-5 * time.Minute)), }}, - AsyncOpInProgress: true, - OperationStartTime: &operationStartTime, - CurrentOperation: v1alpha1.ServiceInstanceOperationProvision, + AsyncOpInProgress: true, + OperationStartTime: &operationStartTime, + CurrentOperation: v1alpha1.ServiceInstanceOperationProvision, + InProgressProperties: &v1alpha1.ServiceInstancePropertiesState{}, } if operation != "" { instance.Status.LastOperation = &operation @@ -546,6 +548,7 @@ func getTestServiceInstanceAsyncDeprovisioning(operation string) *v1alpha1.Servi OperationStartTime: &operationStartTime, CurrentOperation: v1alpha1.ServiceInstanceOperationDeprovision, ReconciledGeneration: 1, + ExternalProperties: &v1alpha1.ServiceInstancePropertiesState{}, } if operation != "" { instance.Status.LastOperation = &operation @@ -1456,26 +1459,6 @@ func assertServiceInstanceReconciledGeneration(t *testing.T, obj runtime.Object, } } -func assertServiceInstanceReconciliationComplete(t *testing.T, obj runtime.Object) { - instance, ok := obj.(*v1alpha1.ServiceInstance) - if !ok { - fatalf(t, "Couldn't convert object %+v into a *v1alpha1.ServiceInstance", obj) - } - if g, rg := instance.Generation, instance.Status.ReconciledGeneration; g != rg { - fatalf(t, "expected Generation and ReconciledGeneration to be equal: Generation %v, ReconciledGeneration %v", g, rg) - } -} - -func assertServiceInstanceReconciliationNotComplete(t *testing.T, obj runtime.Object) { - instance, ok := obj.(*v1alpha1.ServiceInstance) - if !ok { - fatalf(t, "Couldn't convert object %+v into a *v1alpha1.ServiceInstance", obj) - } - if g, rg := instance.Generation, instance.Status.ReconciledGeneration; g <= rg { - fatalf(t, "expected ReconciledGeneration to be less than Generation: Generation %v, ReconciledGeneration %v", g, rg) - } -} - func assertServiceInstanceOperationStartTimeSet(t *testing.T, obj runtime.Object, isOperationStartTimeSet bool) { instance, ok := obj.(*v1alpha1.ServiceInstance) if !ok { @@ -1537,15 +1520,21 @@ func assertServiceInstanceDashboardURL(t *testing.T, obj runtime.Object, dashboa } } -func assertServiceInstanceErrorBeforeRequest(t *testing.T, obj runtime.Object, reason string) { +func assertServiceInstanceErrorBeforeRequest(t *testing.T, obj runtime.Object, reason string, originalInstance *v1alpha1.ServiceInstance) { assertServiceInstanceReadyFalse(t, obj, reason) assertServiceInstanceCurrentOperationClear(t, obj) assertServiceInstanceOperationStartTimeSet(t, obj, false) - assertServiceInstanceReconciliationNotComplete(t, obj) + assertServiceInstanceReconciledGeneration(t, obj, originalInstance.Status.ReconciledGeneration) assertAsyncOpInProgressFalse(t, obj) + assertServiceInstanceInProgressPropertiesNil(t, obj) + assertServiceInstanceExternalPropertiesUnchanged(t, obj, originalInstance) +} + +func assertServiceInstanceOperationInProgress(t *testing.T, obj runtime.Object, operation v1alpha1.ServiceInstanceOperation, originalInstance *v1alpha1.ServiceInstance) { + assertServiceInstanceOperationInProgressWithParameters(t, obj, operation, nil, "", originalInstance) } -func assertServiceInstanceOperationInProgress(t *testing.T, obj runtime.Object, operation v1alpha1.ServiceInstanceOperation) { +func assertServiceInstanceOperationInProgressWithParameters(t *testing.T, obj runtime.Object, operation v1alpha1.ServiceInstanceOperation, inProgressParameters map[string]interface{}, inProgressParametersChecksum string, originalInstance *v1alpha1.ServiceInstance) { reason := "" switch operation { case v1alpha1.ServiceInstanceOperationProvision: @@ -1556,11 +1545,22 @@ func assertServiceInstanceOperationInProgress(t *testing.T, obj runtime.Object, assertServiceInstanceReadyFalse(t, obj, reason) assertServiceInstanceCurrentOperation(t, obj, operation) assertServiceInstanceOperationStartTimeSet(t, obj, true) - assertServiceInstanceReconciliationNotComplete(t, obj) + assertServiceInstanceReconciledGeneration(t, obj, originalInstance.Status.ReconciledGeneration) assertAsyncOpInProgressFalse(t, obj) + switch operation { + case v1alpha1.ServiceInstanceOperationProvision: + assertServiceInstanceInProgressPropertiesParameters(t, obj, inProgressParameters, inProgressParametersChecksum) + case v1alpha1.ServiceInstanceOperationDeprovision: + assertServiceInstanceInProgressPropertiesNil(t, obj) + } + assertServiceInstanceExternalPropertiesUnchanged(t, obj, originalInstance) +} + +func assertServiceInstanceOperationSuccess(t *testing.T, obj runtime.Object, operation v1alpha1.ServiceInstanceOperation, originalInstance *v1alpha1.ServiceInstance) { + assertServiceInstanceOperationSuccessWithParameters(t, obj, operation, nil, "", originalInstance) } -func assertServiceInstanceOperationSuccess(t *testing.T, obj runtime.Object, operation v1alpha1.ServiceInstanceOperation) { +func assertServiceInstanceOperationSuccessWithParameters(t *testing.T, obj runtime.Object, operation v1alpha1.ServiceInstanceOperation, externalParameters map[string]interface{}, externalParametersChecksum string, originalInstance *v1alpha1.ServiceInstance) { var ( reason string readyStatus v1alpha1.ConditionStatus @@ -1576,14 +1576,21 @@ func assertServiceInstanceOperationSuccess(t *testing.T, obj runtime.Object, ope assertServiceInstanceReadyCondition(t, obj, readyStatus, reason) assertServiceInstanceCurrentOperationClear(t, obj) assertServiceInstanceOperationStartTimeSet(t, obj, false) - assertServiceInstanceReconciliationComplete(t, obj) + assertServiceInstanceReconciledGeneration(t, obj, originalInstance.Generation) assertAsyncOpInProgressFalse(t, obj) if operation == v1alpha1.ServiceInstanceOperationDeprovision { assertEmptyFinalizers(t, obj) } + assertServiceInstanceInProgressPropertiesNil(t, obj) + switch operation { + case v1alpha1.ServiceInstanceOperationProvision: + assertServiceInstanceExternalPropertiesParameters(t, obj, externalParameters, externalParametersChecksum) + case v1alpha1.ServiceInstanceOperationDeprovision: + assertServiceInstanceExternalPropertiesNil(t, obj) + } } -func assertServiceInstanceRequestFailingError(t *testing.T, obj runtime.Object, operation v1alpha1.ServiceInstanceOperation, readyReason string, failureReason string) { +func assertServiceInstanceRequestFailingError(t *testing.T, obj runtime.Object, operation v1alpha1.ServiceInstanceOperation, readyReason string, failureReason string, originalInstance *v1alpha1.ServiceInstance) { var readyStatus v1alpha1.ConditionStatus switch operation { case v1alpha1.ServiceInstanceOperationProvision: @@ -1595,11 +1602,17 @@ func assertServiceInstanceRequestFailingError(t *testing.T, obj runtime.Object, assertServiceInstanceCondition(t, obj, v1alpha1.ServiceInstanceConditionFailed, v1alpha1.ConditionTrue, failureReason) assertServiceInstanceCurrentOperationClear(t, obj) assertServiceInstanceOperationStartTimeSet(t, obj, false) - assertServiceInstanceReconciliationComplete(t, obj) + assertServiceInstanceReconciledGeneration(t, obj, originalInstance.Generation) assertAsyncOpInProgressFalse(t, obj) + assertServiceInstanceInProgressPropertiesNil(t, obj) + assertServiceInstanceExternalPropertiesUnchanged(t, obj, originalInstance) } -func assertServiceInstanceRequestRetriableError(t *testing.T, obj runtime.Object, operation v1alpha1.ServiceInstanceOperation, reason string) { +func assertServiceInstanceRequestRetriableError(t *testing.T, obj runtime.Object, operation v1alpha1.ServiceInstanceOperation, reason string, originalInstance *v1alpha1.ServiceInstance) { + assertServiceInstanceRequestRetriableErrorWithParameters(t, obj, operation, reason, nil, "", originalInstance) +} + +func assertServiceInstanceRequestRetriableErrorWithParameters(t *testing.T, obj runtime.Object, operation v1alpha1.ServiceInstanceOperation, reason string, inProgressParameters map[string]interface{}, inProgressParametersChecksum string, originalInstance *v1alpha1.ServiceInstance) { var readyStatus v1alpha1.ConditionStatus switch operation { case v1alpha1.ServiceInstanceOperationProvision: @@ -1610,10 +1623,17 @@ func assertServiceInstanceRequestRetriableError(t *testing.T, obj runtime.Object assertServiceInstanceReadyCondition(t, obj, readyStatus, reason) assertServiceInstanceCurrentOperation(t, obj, operation) assertServiceInstanceOperationStartTimeSet(t, obj, true) - assertServiceInstanceReconciliationNotComplete(t, obj) + assertServiceInstanceReconciledGeneration(t, obj, originalInstance.Status.ReconciledGeneration) + switch operation { + case v1alpha1.ServiceInstanceOperationProvision: + assertServiceInstanceInProgressPropertiesParameters(t, obj, inProgressParameters, inProgressParametersChecksum) + case v1alpha1.ServiceInstanceOperationDeprovision: + assertServiceInstanceInProgressPropertiesNil(t, obj) + } + assertServiceInstanceExternalPropertiesUnchanged(t, obj, originalInstance) } -func assertServiceInstanceAsyncInProgress(t *testing.T, obj runtime.Object, operation v1alpha1.ServiceInstanceOperation, operationKey string) { +func assertServiceInstanceAsyncInProgress(t *testing.T, obj runtime.Object, operation v1alpha1.ServiceInstanceOperation, operationKey string, originalInstance *v1alpha1.ServiceInstance) { reason := "" switch operation { case v1alpha1.ServiceInstanceOperationProvision: @@ -1625,7 +1645,7 @@ func assertServiceInstanceAsyncInProgress(t *testing.T, obj runtime.Object, oper assertServiceInstanceLastOperation(t, obj, operationKey) assertServiceInstanceCurrentOperation(t, obj, operation) assertServiceInstanceOperationStartTimeSet(t, obj, true) - assertServiceInstanceReconciliationNotComplete(t, obj) + assertServiceInstanceReconciledGeneration(t, obj, originalInstance.Status.ReconciledGeneration) assertAsyncOpInProgressTrue(t, obj) } @@ -1642,7 +1662,107 @@ func assertServiceInstanceConditionHasLastOperationDescription(t *testing.T, obj expected = fmt.Sprintf("%s (%s)", asyncDeprovisioningMessage, lastOperationDescription) } if e, a := expected, instance.Status.Conditions[0].Message; e != a { + fatalf(t, "unexpected condition message: expected %q, got %q", e, a) + } +} + +func assertServiceInstanceInProgressPropertiesNil(t *testing.T, obj runtime.Object) { + instance, ok := obj.(*v1alpha1.ServiceInstance) + if !ok { + fatalf(t, "Couldn't convert object %+v into a *v1alpha1.ServiceInstance", obj) + } + + if a := instance.Status.InProgressProperties; a != nil { + fatalf(t, "expected in-progress properties to be nil: actual %v", a) + } +} + +func assertServiceInstanceInProgressPropertiesParameters(t *testing.T, obj runtime.Object, params map[string]interface{}, checksum string) { + instance, ok := obj.(*v1alpha1.ServiceInstance) + if !ok { + fatalf(t, "Couldn't convert object %+v into a *v1alpha1.ServiceInstance", obj) + } + assertServiceInstancePropertiesStateParameters(t, "in-progress", instance.Status.InProgressProperties, params, checksum) +} + +func assertServiceInstanceInProgressPropertiesUnchanged(t *testing.T, obj runtime.Object, originalInstance *v1alpha1.ServiceInstance) { + instance, ok := obj.(*v1alpha1.ServiceInstance) + if !ok { + fatalf(t, "Couldn't convert object %+v into a *v1alpha1.ServiceInstance", obj) + } + if originalInstance.Status.InProgressProperties == nil { + assertServiceInstanceInProgressPropertiesNil(t, obj) + } else { + assertServiceInstancePropertiesStateParametersUnchanged(t, "in-progress", instance.Status.InProgressProperties, *originalInstance.Status.InProgressProperties) + } +} + +func assertServiceInstanceExternalPropertiesNil(t *testing.T, obj runtime.Object) { + instance, ok := obj.(*v1alpha1.ServiceInstance) + if !ok { + fatalf(t, "Couldn't convert object %+v into a *v1alpha1.ServiceInstance", obj) + } + + if a := instance.Status.ExternalProperties; a != nil { + fatalf(t, "expected external properties to be nil: actual %v", a) + } +} + +func assertServiceInstanceExternalPropertiesParameters(t *testing.T, obj runtime.Object, params map[string]interface{}, checksum string) { + instance, ok := obj.(*v1alpha1.ServiceInstance) + if !ok { + fatalf(t, "Couldn't convert object %+v into a *v1alpha1.ServiceInstance", obj) + } + assertServiceInstancePropertiesStateParameters(t, "external", instance.Status.ExternalProperties, params, checksum) +} + +func assertServiceInstanceExternalPropertiesUnchanged(t *testing.T, obj runtime.Object, originalInstance *v1alpha1.ServiceInstance) { + instance, ok := obj.(*v1alpha1.ServiceInstance) + if !ok { + fatalf(t, "Couldn't convert object %+v into a *v1alpha1.ServiceInstance", obj) + } + if originalInstance.Status.ExternalProperties == nil { + assertServiceInstanceExternalPropertiesNil(t, obj) + } else { + assertServiceInstancePropertiesStateParametersUnchanged(t, "external", instance.Status.ExternalProperties, *originalInstance.Status.ExternalProperties) + } +} + +func assertServiceInstancePropertiesStateParameters(t *testing.T, propsLabel string, actualProps *v1alpha1.ServiceInstancePropertiesState, expectedParams map[string]interface{}, expectedChecksum string) { + if actualProps == nil { + fatalf(t, "expected %v properties to not be nil", propsLabel) + } + assertPropertiesStateParameters(t, propsLabel, actualProps.Parameters, expectedParams) + if e, a := expectedChecksum, actualProps.ParametersChecksum; e != a { + fatalf(t, "unexpected %v properties parameters checksum: expected %v, actual %v", propsLabel, e, a) + } +} + +func assertPropertiesStateParameters(t *testing.T, propsLabel string, marshalledParams *runtime.RawExtension, expectedParams map[string]interface{}) { + if expectedParams == nil { + if a := marshalledParams; a != nil { + fatalf(t, "expected %v properties parameters to be nil: actual %v", propsLabel, a) + } + } else { + if marshalledParams == nil { + fatalf(t, "expected %v properties parameters to not be nil", propsLabel) + } + actualParams := make(map[string]interface{}) + if err := yaml.Unmarshal(marshalledParams.Raw, &actualParams); err != nil { + fatalf(t, "%v properties parameters could not be unmarshalled: %v", propsLabel, err) + } + if e, a := expectedParams, actualParams; !reflect.DeepEqual(e, a) { + fatalf(t, "unexpected %v properties parameters: expected %v, actual %v", propsLabel, e, a) + } + } +} +func assertServiceInstancePropertiesStateParametersUnchanged(t *testing.T, propsLabel string, new *v1alpha1.ServiceInstancePropertiesState, old v1alpha1.ServiceInstancePropertiesState) { + if new == nil { + fatalf(t, "expected %v properties to not be nil", propsLabel) + } + if e, a := old, *new; !reflect.DeepEqual(e, a) { + fatalf(t, "unexpected %v properties: expected %v, actual %v", propsLabel, e, a) } } @@ -1694,16 +1814,6 @@ func assertServiceInstanceCredentialReconciledGeneration(t *testing.T, obj runti } } -func assertServiceInstanceCredentialReconciliationComplete(t *testing.T, obj runtime.Object) { - binding, ok := obj.(*v1alpha1.ServiceInstanceCredential) - if !ok { - fatalf(t, "Couldn't convert object %+v into a *v1alpha1.ServiceInstanceCredential", obj) - } - if g, rg := binding.Generation, binding.Status.ReconciledGeneration; g != rg { - fatalf(t, "expected Generation and ReconciledGeneration to be equal: Generation %v, ReconciledGeneration %v", g, rg) - } -} - func assertServiceInstanceCredentialReconciliationNotComplete(t *testing.T, obj runtime.Object) { binding, ok := obj.(*v1alpha1.ServiceInstanceCredential) if !ok { @@ -1734,24 +1844,30 @@ func assertServiceInstanceCredentialCurrentOperationClear(t *testing.T, obj runt } func assertServiceInstanceCredentialCurrentOperation(t *testing.T, obj runtime.Object, currentOperation v1alpha1.ServiceInstanceCredentialOperation) { - instance, ok := obj.(*v1alpha1.ServiceInstanceCredential) + binding, ok := obj.(*v1alpha1.ServiceInstanceCredential) if !ok { fatalf(t, "Couldn't convert object %+v into a *v1alpha1.ServiceInstanceCredential", obj) } - if e, a := currentOperation, instance.Status.CurrentOperation; e != a { + if e, a := currentOperation, binding.Status.CurrentOperation; e != a { fatalf(t, "unexpected current operation: expected %q, got %q", e, a) } } -func assertServiceInstanceCredentialErrorBeforeRequest(t *testing.T, obj runtime.Object, reason string) { +func assertServiceInstanceCredentialErrorBeforeRequest(t *testing.T, obj runtime.Object, reason string, originalBinding *v1alpha1.ServiceInstanceCredential) { assertServiceInstanceCredentialReadyFalse(t, obj, reason) assertServiceInstanceCredentialCurrentOperationClear(t, obj) assertServiceInstanceCredentialOperationStartTimeSet(t, obj, false) - assertServiceInstanceCredentialReconciliationNotComplete(t, obj) + assertServiceInstanceCredentialReconciledGeneration(t, obj, originalBinding.Status.ReconciledGeneration) + assertServiceInstanceCredentialInProgressPropertiesNil(t, obj) + assertServiceInstanceCredentialExternalPropertiesUnchanged(t, obj, originalBinding) } -func assertServiceInstanceCredentialOperationInProgress(t *testing.T, obj runtime.Object, operation v1alpha1.ServiceInstanceCredentialOperation) { +func assertServiceInstanceCredentialOperationInProgress(t *testing.T, obj runtime.Object, operation v1alpha1.ServiceInstanceCredentialOperation, originalBinding *v1alpha1.ServiceInstanceCredential) { + assertServiceInstanceCredentialOperationInProgressWithParameters(t, obj, operation, nil, "", originalBinding) +} + +func assertServiceInstanceCredentialOperationInProgressWithParameters(t *testing.T, obj runtime.Object, operation v1alpha1.ServiceInstanceCredentialOperation, inProgressParameters map[string]interface{}, inProgressParametersChecksum string, originalBinding *v1alpha1.ServiceInstanceCredential) { reason := "" switch operation { case v1alpha1.ServiceInstanceCredentialOperationBind: @@ -1762,10 +1878,21 @@ func assertServiceInstanceCredentialOperationInProgress(t *testing.T, obj runtim assertServiceInstanceCredentialReadyFalse(t, obj, reason) assertServiceInstanceCredentialCurrentOperation(t, obj, operation) assertServiceInstanceCredentialOperationStartTimeSet(t, obj, true) - assertServiceInstanceCredentialReconciliationNotComplete(t, obj) + assertServiceInstanceCredentialReconciledGeneration(t, obj, originalBinding.Status.ReconciledGeneration) + switch operation { + case v1alpha1.ServiceInstanceCredentialOperationBind: + assertServiceInstanceCredentialInProgressPropertiesParameters(t, obj, inProgressParameters, inProgressParametersChecksum) + case v1alpha1.ServiceInstanceCredentialOperationUnbind: + assertServiceInstanceCredentialInProgressPropertiesNil(t, obj) + } + assertServiceInstanceCredentialExternalPropertiesUnchanged(t, obj, originalBinding) +} + +func assertServiceInstanceCredentialOperationSuccess(t *testing.T, obj runtime.Object, operation v1alpha1.ServiceInstanceCredentialOperation, originalBinding *v1alpha1.ServiceInstanceCredential) { + assertServiceInstanceCredentialOperationSuccessWithParameters(t, obj, operation, nil, "", originalBinding) } -func assertServiceInstanceCredentialOperationSuccess(t *testing.T, obj runtime.Object, operation v1alpha1.ServiceInstanceCredentialOperation) { +func assertServiceInstanceCredentialOperationSuccessWithParameters(t *testing.T, obj runtime.Object, operation v1alpha1.ServiceInstanceCredentialOperation, externalParameters map[string]interface{}, externalParametersChecksum string, originalBinding *v1alpha1.ServiceInstanceCredential) { var ( reason string readyStatus v1alpha1.ConditionStatus @@ -1781,13 +1908,20 @@ func assertServiceInstanceCredentialOperationSuccess(t *testing.T, obj runtime.O assertServiceInstanceCredentialReadyCondition(t, obj, readyStatus, reason) assertServiceInstanceCredentialCurrentOperationClear(t, obj) assertServiceInstanceCredentialOperationStartTimeSet(t, obj, false) - assertServiceInstanceCredentialReconciliationComplete(t, obj) + assertServiceInstanceCredentialReconciledGeneration(t, obj, originalBinding.Generation) if operation == v1alpha1.ServiceInstanceCredentialOperationUnbind { assertEmptyFinalizers(t, obj) } + assertServiceInstanceCredentialInProgressPropertiesNil(t, obj) + switch operation { + case v1alpha1.ServiceInstanceCredentialOperationBind: + assertServiceInstanceCredentialExternalPropertiesParameters(t, obj, externalParameters, externalParametersChecksum) + case v1alpha1.ServiceInstanceCredentialOperationUnbind: + assertServiceInstanceCredentialExternalPropertiesNil(t, obj) + } } -func assertServiceInstanceCredentialRequestFailingError(t *testing.T, obj runtime.Object, operation v1alpha1.ServiceInstanceCredentialOperation, readyReason string, failureReason string) { +func assertServiceInstanceCredentialRequestFailingError(t *testing.T, obj runtime.Object, operation v1alpha1.ServiceInstanceCredentialOperation, readyReason string, failureReason string, originalBinding *v1alpha1.ServiceInstanceCredential) { var readyStatus v1alpha1.ConditionStatus switch operation { case v1alpha1.ServiceInstanceCredentialOperationBind: @@ -1799,10 +1933,16 @@ func assertServiceInstanceCredentialRequestFailingError(t *testing.T, obj runtim assertServiceInstanceCredentialCondition(t, obj, v1alpha1.ServiceInstanceCredentialConditionFailed, v1alpha1.ConditionTrue, failureReason) assertServiceInstanceCredentialCurrentOperationClear(t, obj) assertServiceInstanceCredentialOperationStartTimeSet(t, obj, false) - assertServiceInstanceCredentialReconciliationComplete(t, obj) + assertServiceInstanceCredentialReconciledGeneration(t, obj, originalBinding.Generation) + assertServiceInstanceCredentialInProgressPropertiesNil(t, obj) + assertServiceInstanceCredentialExternalPropertiesUnchanged(t, obj, originalBinding) +} + +func assertServiceInstanceCredentialRequestRetriableError(t *testing.T, obj runtime.Object, operation v1alpha1.ServiceInstanceCredentialOperation, reason string, originalBinding *v1alpha1.ServiceInstanceCredential) { + assertServiceInstanceCredentialRequestRetriableErrorWithParameters(t, obj, operation, reason, nil, "", originalBinding) } -func assertServiceInstanceCredentialRequestRetriableError(t *testing.T, obj runtime.Object, operation v1alpha1.ServiceInstanceCredentialOperation, reason string) { +func assertServiceInstanceCredentialRequestRetriableErrorWithParameters(t *testing.T, obj runtime.Object, operation v1alpha1.ServiceInstanceCredentialOperation, reason string, inProgressParameters map[string]interface{}, inProgressParametersChecksum string, originalBinding *v1alpha1.ServiceInstanceCredential) { var readyStatus v1alpha1.ConditionStatus switch operation { case v1alpha1.ServiceInstanceCredentialOperationBind: @@ -1813,7 +1953,95 @@ func assertServiceInstanceCredentialRequestRetriableError(t *testing.T, obj runt assertServiceInstanceCredentialReadyCondition(t, obj, readyStatus, reason) assertServiceInstanceCredentialCurrentOperation(t, obj, operation) assertServiceInstanceCredentialOperationStartTimeSet(t, obj, true) - assertServiceInstanceCredentialReconciliationNotComplete(t, obj) + assertServiceInstanceCredentialReconciledGeneration(t, obj, originalBinding.Status.ReconciledGeneration) + switch operation { + case v1alpha1.ServiceInstanceCredentialOperationBind: + assertServiceInstanceCredentialInProgressPropertiesParameters(t, obj, inProgressParameters, inProgressParametersChecksum) + case v1alpha1.ServiceInstanceCredentialOperationUnbind: + assertServiceInstanceCredentialInProgressPropertiesNil(t, obj) + } + assertServiceInstanceCredentialExternalPropertiesUnchanged(t, obj, originalBinding) +} + +func assertServiceInstanceCredentialInProgressPropertiesNil(t *testing.T, obj runtime.Object) { + binding, ok := obj.(*v1alpha1.ServiceInstanceCredential) + if !ok { + fatalf(t, "Couldn't convert object %+v into a *v1alpha1.ServiceInstanceCredential", obj) + } + + if a := binding.Status.InProgressProperties; a != nil { + fatalf(t, "expected in-progress properties to be nil: actual %v", a) + } +} + +func assertServiceInstanceCredentialInProgressPropertiesParameters(t *testing.T, obj runtime.Object, params map[string]interface{}, checksum string) { + binding, ok := obj.(*v1alpha1.ServiceInstanceCredential) + if !ok { + fatalf(t, "Couldn't convert object %+v into a *v1alpha1.ServiceInstanceCredential", obj) + } + assertServiceInstanceCredentialPropertiesStateParameters(t, "in-progress", binding.Status.InProgressProperties, params, checksum) +} + +func assertServiceInstanceCredentialInProgressPropertiesUnchanged(t *testing.T, obj runtime.Object, originalBinding *v1alpha1.ServiceInstanceCredential) { + binding, ok := obj.(*v1alpha1.ServiceInstanceCredential) + if !ok { + fatalf(t, "Couldn't convert object %+v into a *v1alpha1.ServiceInstanceCredential", obj) + } + if originalBinding.Status.InProgressProperties == nil { + assertServiceInstanceCredentialInProgressPropertiesNil(t, obj) + } else { + assertServiceInstanceCredentialPropertiesStateParametersUnchanged(t, "in-progress", binding.Status.InProgressProperties, *originalBinding.Status.InProgressProperties) + } +} + +func assertServiceInstanceCredentialExternalPropertiesNil(t *testing.T, obj runtime.Object) { + binding, ok := obj.(*v1alpha1.ServiceInstanceCredential) + if !ok { + fatalf(t, "Couldn't convert object %+v into a *v1alpha1.ServiceInstanceCredential", obj) + } + + if a := binding.Status.ExternalProperties; a != nil { + fatalf(t, "expected external properties to be nil: actual %v", a) + } +} + +func assertServiceInstanceCredentialExternalPropertiesParameters(t *testing.T, obj runtime.Object, params map[string]interface{}, checksum string) { + binding, ok := obj.(*v1alpha1.ServiceInstanceCredential) + if !ok { + fatalf(t, "Couldn't convert object %+v into a *v1alpha1.ServiceInstanceCredential", obj) + } + assertServiceInstanceCredentialPropertiesStateParameters(t, "external", binding.Status.ExternalProperties, params, checksum) +} + +func assertServiceInstanceCredentialExternalPropertiesUnchanged(t *testing.T, obj runtime.Object, originalBinding *v1alpha1.ServiceInstanceCredential) { + binding, ok := obj.(*v1alpha1.ServiceInstanceCredential) + if !ok { + fatalf(t, "Couldn't convert object %+v into a *v1alpha1.ServiceInstanceCredential", obj) + } + if originalBinding.Status.ExternalProperties == nil { + assertServiceInstanceCredentialExternalPropertiesNil(t, obj) + } else { + assertServiceInstanceCredentialPropertiesStateParametersUnchanged(t, "external", binding.Status.ExternalProperties, *originalBinding.Status.ExternalProperties) + } +} + +func assertServiceInstanceCredentialPropertiesStateParameters(t *testing.T, propsLabel string, actualProps *v1alpha1.ServiceInstanceCredentialPropertiesState, expectedParams map[string]interface{}, expectedChecksum string) { + if actualProps == nil { + fatalf(t, "expected %v properties to not be nil", propsLabel) + } + assertPropertiesStateParameters(t, propsLabel, actualProps.Parameters, expectedParams) + if e, a := expectedChecksum, actualProps.ParametersChecksum; e != a { + fatalf(t, "unexpected %v properties parameters checksum: expected %v, actual %v", propsLabel, e, a) + } +} + +func assertServiceInstanceCredentialPropertiesStateParametersUnchanged(t *testing.T, propsLabel string, new *v1alpha1.ServiceInstanceCredentialPropertiesState, old v1alpha1.ServiceInstanceCredentialPropertiesState) { + if new == nil { + fatalf(t, "expected %v properties to not be nil", propsLabel) + } + if e, a := old, *new; !reflect.DeepEqual(e, a) { + fatalf(t, "unexpected %v properties: expected %v, actual %v", propsLabel, e, a) + } } func assertEmptyFinalizers(t *testing.T, obj runtime.Object) { diff --git a/pkg/controller/parameters.go b/pkg/controller/parameters.go index 84e120ad62b..7a66e78bb54 100644 --- a/pkg/controller/parameters.go +++ b/pkg/controller/parameters.go @@ -17,6 +17,7 @@ limitations under the License. package controller import ( + "crypto/sha256" "encoding/json" "fmt" @@ -28,36 +29,44 @@ import ( ) // buildParameters generates the parameters JSON structure to be passed -// to the broker -func buildParameters(kubeClient kubernetes.Interface, namespace string, parametersFrom []v1alpha1.ParametersFromSource, parameters *runtime.RawExtension) (map[string]interface{}, error) { +// to the broker. +// The first return value is a map of parameters to send to the Broker, including +// secret values. +// The second return value is a map of parameters with secret values redacted, +// replaced with "". +// The third return value is any error that caused the function to fail. +func buildParameters(kubeClient kubernetes.Interface, namespace string, parametersFrom []v1alpha1.ParametersFromSource, parameters *runtime.RawExtension) (map[string]interface{}, map[string]interface{}, error) { params := make(map[string]interface{}) + paramsWithSecretsRedacted := make(map[string]interface{}) if parametersFrom != nil { for _, p := range parametersFrom { fps, err := fetchParametersFromSource(kubeClient, namespace, &p) if err != nil { - return nil, err + return nil, nil, err } for k, v := range fps { if _, ok := params[k]; ok { - return nil, fmt.Errorf("conflict: duplicate entry for parameter %q", k) + return nil, nil, fmt.Errorf("conflict: duplicate entry for parameter %q", k) } params[k] = v + paramsWithSecretsRedacted[k] = "" } } } if parameters != nil { pp, err := UnmarshalRawParameters(parameters.Raw) if err != nil { - return nil, err + return nil, nil, err } for k, v := range pp { if _, ok := params[k]; ok { - return nil, fmt.Errorf("conflict: duplicate entry for parameter %q", k) + return nil, nil, fmt.Errorf("conflict: duplicate entry for parameter %q", k) } params[k] = v + paramsWithSecretsRedacted[k] = v } } - return params, nil + return params, paramsWithSecretsRedacted, nil } // fetchParametersFromSource fetches data from a specified external source and @@ -90,6 +99,11 @@ func UnmarshalRawParameters(in []byte) (map[string]interface{}, error) { return parameters, nil } +// MarshalRawParameters marshals the specified map of parameters into YAML +func MarshalRawParameters(in map[string]interface{}) ([]byte, error) { + return yaml.Marshal(in) +} + // unmarshalJSON produces a map structure from a given raw JSON input func unmarshalJSON(in []byte) (map[string]interface{}, error) { parameters := make(map[string]interface{}) @@ -107,3 +121,14 @@ func fetchSecretKeyValue(kubeClient kubernetes.Interface, namespace string, secr } return secret.Data[secretKeyRef.Key], nil } + +// generateChecksumOfParameters generates a checksum for the map of parameters. +// This checksum is used to determine if parameters have changed. +func generateChecksumOfParameters(params map[string]interface{}) (string, error) { + paramsAsJSON, err := json.Marshal(params) + if err != nil { + return "", err + } + hash := sha256.Sum256(paramsAsJSON) + return fmt.Sprintf("%x", hash), nil +} diff --git a/pkg/controller/parameters_test.go b/pkg/controller/parameters_test.go index e751e92ee12..0298d8ccd23 100644 --- a/pkg/controller/parameters_test.go +++ b/pkg/controller/parameters_test.go @@ -36,19 +36,24 @@ func TestBuildParameters(t *testing.T) { } cases := []struct { - name string - parametersFrom []v1alpha1.ParametersFromSource - parameters *runtime.RawExtension - secret *v1.Secret - expected map[string]interface{} - shouldSucceed bool + name string + parametersFrom []v1alpha1.ParametersFromSource + parameters *runtime.RawExtension + secret *v1.Secret + expectedParameters map[string]interface{} + expectedParametersWithSecretsRedacted map[string]interface{} + shouldSucceed bool }{ { name: "parameters: basic", parameters: &runtime.RawExtension{ Raw: []byte(`{ "p1": "v1", "p2": "v2" }`), }, - expected: map[string]interface{}{ + expectedParameters: map[string]interface{}{ + "p1": "v1", + "p2": "v2", + }, + expectedParametersWithSecretsRedacted: map[string]interface{}{ "p1": "v1", "p2": "v2", }, @@ -72,9 +77,12 @@ func TestBuildParameters(t *testing.T) { }, }, secret: secret, - expected: map[string]interface{}{ + expectedParameters: map[string]interface{}{ "json": true, }, + expectedParametersWithSecretsRedacted: map[string]interface{}{ + "json": "", + }, shouldSucceed: true, }, { @@ -104,10 +112,14 @@ func TestBuildParameters(t *testing.T) { Raw: []byte(`{ "p1": "v1" }`), }, secret: secret, - expected: map[string]interface{}{ + expectedParameters: map[string]interface{}{ "json": true, "p1": "v1", }, + expectedParametersWithSecretsRedacted: map[string]interface{}{ + "json": "", + "p1": "v1", + }, shouldSucceed: true, }, { @@ -130,12 +142,12 @@ func TestBuildParameters(t *testing.T) { for _, tc := range cases { t.Run(tc.name, func(t *testing.T) { - testBuildParameters(t, tc.parametersFrom, tc.parameters, tc.secret, tc.expected, tc.shouldSucceed) + testBuildParameters(t, tc.parametersFrom, tc.parameters, tc.secret, tc.expectedParameters, tc.expectedParametersWithSecretsRedacted, tc.shouldSucceed) }) } } -func testBuildParameters(t *testing.T, parametersFrom []v1alpha1.ParametersFromSource, parameters *runtime.RawExtension, secret *v1.Secret, expected map[string]interface{}, shouldSucceed bool) { +func testBuildParameters(t *testing.T, parametersFrom []v1alpha1.ParametersFromSource, parameters *runtime.RawExtension, secret *v1.Secret, expected map[string]interface{}, expectedWithSecretsRdacted map[string]interface{}, shouldSucceed bool) { // create a fake kube client fakeKubeClient := &clientgofake.Clientset{} if secret != nil { @@ -144,7 +156,7 @@ func testBuildParameters(t *testing.T, parametersFrom []v1alpha1.ParametersFromS addGetSecretNotFoundReaction(fakeKubeClient) } - actual, err := buildParameters(fakeKubeClient, "test-ns", parametersFrom, parameters) + actual, actualWithSecretsRedacted, err := buildParameters(fakeKubeClient, "test-ns", parametersFrom, parameters) if shouldSucceed { if err != nil { t.Fatalf("Failed to build parameters: %v", err) @@ -152,9 +164,66 @@ func testBuildParameters(t *testing.T, parametersFrom []v1alpha1.ParametersFromS if !reflect.DeepEqual(actual, expected) { t.Fatalf("incorrect result: diff \n%v", diff.ObjectGoPrintSideBySide(expected, actual)) } + if !reflect.DeepEqual(actualWithSecretsRedacted, expectedWithSecretsRdacted) { + t.Fatalf("incorrect result with redacted secrets: diff \n%v", diff.ObjectGoPrintSideBySide(expectedWithSecretsRdacted, actualWithSecretsRedacted)) + } } else { if err == nil { t.Fatal("Expected error, but got success") } } } + +func TestGenerateChecksumOfParameters(t *testing.T) { + cases := []struct { + name string + oldParams map[string]interface{} + newParams map[string]interface{} + expectedEquality bool + }{ + { + name: "same", + oldParams: map[string]interface{}{ + "a": "first", + "b": 2, + }, + newParams: map[string]interface{}{ + "a": "first", + "b": 2, + }, + expectedEquality: true, + }, + { + name: "different", + oldParams: map[string]interface{}{ + "a": "first", + "b": 2, + }, + newParams: map[string]interface{}{ + "a": "first", + "b": 3, + }, + expectedEquality: false, + }, + } + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + oldChecksum, err := generateChecksumOfParameters(tc.oldParams) + if err != nil { + t.Fatalf("failed to generate checksum: %v", err) + } + newChecksum, err := generateChecksumOfParameters(tc.newParams) + if err != nil { + t.Fatalf("failed to generate checksum: %v", err) + } + actualEquality := oldChecksum == newChecksum + if e, a := tc.expectedEquality, actualEquality; e != a { + expectedCondition := "be equal" + if !tc.expectedEquality { + expectedCondition = "not be equal" + } + t.Fatalf("expected checksums to %s: old %q, new %q", expectedCondition, oldChecksum, newChecksum) + } + }) + } +} diff --git a/pkg/openapi/openapi_generated.go b/pkg/openapi/openapi_generated.go index 8bf7d67a4cb..5c179d6eb26 100644 --- a/pkg/openapi/openapi_generated.go +++ b/pkg/openapi/openapi_generated.go @@ -744,6 +744,36 @@ func GetOpenAPIDefinitions(ref openapi.ReferenceCallback) map[string]openapi.Ope Dependencies: []string{ "github.com/kubernetes-incubator/service-catalog/pkg/apis/servicecatalog/v1alpha1.ServiceInstanceCredential", "k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"}, }, + "github.com/kubernetes-incubator/service-catalog/pkg/apis/servicecatalog/v1alpha1.ServiceInstanceCredentialPropertiesState": { + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "ServiceInstanceCredentialPropertiesState is the state of a ServiceInstanceCredential that the ServiceBroker knows about.", + Properties: map[string]spec.Schema{ + "parameters": { + SchemaProps: spec.SchemaProps{ + Description: "Parameters is a blob of the parameters and their values that the broker knows about for this ServiceInstanceCredential. If a parameter was sourced from a secret, its value will be \"\" in this blob.", + Ref: ref("k8s.io/apimachinery/pkg/runtime.RawExtension"), + }, + }, + "parameterChecksum": { + SchemaProps: spec.SchemaProps{ + Description: "ParametersChecksum is the checksum of the parameters that were sent.", + Type: []string{"string"}, + Format: "", + }, + }, + "userInfo": { + SchemaProps: spec.SchemaProps{ + Description: "UserInfo is information about the user that made the request.", + Ref: ref("github.com/kubernetes-incubator/service-catalog/pkg/apis/servicecatalog/v1alpha1.UserInfo"), + }, + }, + }, + }, + }, + Dependencies: []string{ + "github.com/kubernetes-incubator/service-catalog/pkg/apis/servicecatalog/v1alpha1.UserInfo", "k8s.io/apimachinery/pkg/runtime.RawExtension"}, + }, "github.com/kubernetes-incubator/service-catalog/pkg/apis/servicecatalog/v1alpha1.ServiceInstanceCredentialSpec": { Schema: spec.Schema{ SchemaProps: spec.SchemaProps{ @@ -838,12 +868,24 @@ func GetOpenAPIDefinitions(ref openapi.ReferenceCallback) map[string]openapi.Ope Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.Time"), }, }, + "inProgressProperties": { + SchemaProps: spec.SchemaProps{ + Description: "InProgressProperties is the properties state for which there is a bind operation in progress.", + Ref: ref("github.com/kubernetes-incubator/service-catalog/pkg/apis/servicecatalog/v1alpha1.ServiceInstanceCredentialPropertiesState"), + }, + }, + "externalProperties": { + SchemaProps: spec.SchemaProps{ + Description: "ExternalProperties is the properties state that the broker knows about for this ServiceInstanceCredential.", + Ref: ref("github.com/kubernetes-incubator/service-catalog/pkg/apis/servicecatalog/v1alpha1.ServiceInstanceCredentialPropertiesState"), + }, + }, }, Required: []string{"conditions", "reconciledGeneration"}, }, }, Dependencies: []string{ - "github.com/kubernetes-incubator/service-catalog/pkg/apis/servicecatalog/v1alpha1.ServiceInstanceCredentialCondition", "k8s.io/apimachinery/pkg/apis/meta/v1.Time"}, + "github.com/kubernetes-incubator/service-catalog/pkg/apis/servicecatalog/v1alpha1.ServiceInstanceCredentialCondition", "github.com/kubernetes-incubator/service-catalog/pkg/apis/servicecatalog/v1alpha1.ServiceInstanceCredentialPropertiesState", "k8s.io/apimachinery/pkg/apis/meta/v1.Time"}, }, "github.com/kubernetes-incubator/service-catalog/pkg/apis/servicecatalog/v1alpha1.ServiceInstanceList": { Schema: spec.Schema{ @@ -888,6 +930,44 @@ func GetOpenAPIDefinitions(ref openapi.ReferenceCallback) map[string]openapi.Ope Dependencies: []string{ "github.com/kubernetes-incubator/service-catalog/pkg/apis/servicecatalog/v1alpha1.ServiceInstance", "k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"}, }, + "github.com/kubernetes-incubator/service-catalog/pkg/apis/servicecatalog/v1alpha1.ServiceInstancePropertiesState": { + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "ServiceInstancePropertiesState is the state of a ServiceInstance that the ServiceBroker knows about.", + Properties: map[string]spec.Schema{ + "planName": { + SchemaProps: spec.SchemaProps{ + Description: "PlanName is the name of the plan that the broker knows this ServiceInstance to be on.", + Type: []string{"string"}, + Format: "", + }, + }, + "parameters": { + SchemaProps: spec.SchemaProps{ + Description: "Parameters is a blob of the parameters and their values that the broker knows about for this ServiceInstance. If a parameter was sourced from a secret, its value will be \"\" in this blob.", + Ref: ref("k8s.io/apimachinery/pkg/runtime.RawExtension"), + }, + }, + "parameterChecksum": { + SchemaProps: spec.SchemaProps{ + Description: "ParametersChecksum is the checksum of the parameters that were sent.", + Type: []string{"string"}, + Format: "", + }, + }, + "userInfo": { + SchemaProps: spec.SchemaProps{ + Description: "UserInfo is information about the user that made the request.", + Ref: ref("github.com/kubernetes-incubator/service-catalog/pkg/apis/servicecatalog/v1alpha1.UserInfo"), + }, + }, + }, + Required: []string{"planName"}, + }, + }, + Dependencies: []string{ + "github.com/kubernetes-incubator/service-catalog/pkg/apis/servicecatalog/v1alpha1.UserInfo", "k8s.io/apimachinery/pkg/runtime.RawExtension"}, + }, "github.com/kubernetes-incubator/service-catalog/pkg/apis/servicecatalog/v1alpha1.ServiceInstanceSpec": { Schema: spec.Schema{ SchemaProps: spec.SchemaProps{ @@ -1005,12 +1085,24 @@ func GetOpenAPIDefinitions(ref openapi.ReferenceCallback) map[string]openapi.Ope Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.Time"), }, }, + "inProgressProperties": { + SchemaProps: spec.SchemaProps{ + Description: "InProgressProperties is the properties state for which there is a provision or update action in progress.", + Ref: ref("github.com/kubernetes-incubator/service-catalog/pkg/apis/servicecatalog/v1alpha1.ServiceInstancePropertiesState"), + }, + }, + "externalProperties": { + SchemaProps: spec.SchemaProps{ + Description: "ExternalProperties is the properites state which the broker knows about.", + Ref: ref("github.com/kubernetes-incubator/service-catalog/pkg/apis/servicecatalog/v1alpha1.ServiceInstancePropertiesState"), + }, + }, }, Required: []string{"conditions", "asyncOpInProgress", "reconciledGeneration"}, }, }, Dependencies: []string{ - "github.com/kubernetes-incubator/service-catalog/pkg/apis/servicecatalog/v1alpha1.ServiceInstanceCondition", "k8s.io/apimachinery/pkg/apis/meta/v1.Time"}, + "github.com/kubernetes-incubator/service-catalog/pkg/apis/servicecatalog/v1alpha1.ServiceInstanceCondition", "github.com/kubernetes-incubator/service-catalog/pkg/apis/servicecatalog/v1alpha1.ServiceInstancePropertiesState", "k8s.io/apimachinery/pkg/apis/meta/v1.Time"}, }, "github.com/kubernetes-incubator/service-catalog/pkg/apis/servicecatalog/v1alpha1.ServicePlan": { Schema: spec.Schema{